Skip to content

Commit

Permalink
Merge pull request #4 from Meltwin/projections
Browse files Browse the repository at this point in the history
v1.0.0 - Working Base Software
  • Loading branch information
Meltwin authored Jan 6, 2025
2 parents 0dfe335 + 4b0f575 commit efc2d00
Show file tree
Hide file tree
Showing 21 changed files with 924 additions and 124 deletions.
141 changes: 141 additions & 0 deletions include/kami/export/color.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#ifndef KAMI_COLOR
#define KAMI_COLOR

#include <cmath>
#include <cstdlib>
#include <iostream>
#include <random>
#include <sstream>
#include <vector>

namespace kami::color {

typedef unsigned long ulong;

struct Color {
double r, g, b;

Color whiten() { return Color{(r + 1) / 2, (g + 1) / 2, (b + 1) / 2}; }

// Maths
static double distance2(const Color &c1, const Color &c2) {
return (c1.r - c2.r) * (c1.r - c2.r) + (c1.g - c2.g) * (c1.g - c2.g) +
(c1.b - c2.b) * (c1.b - c2.b);
}
static double distance(const Color &c1, const Color &c2) {
return std::sqrt(Color::distance2(c1, c2));
}

std::string str() {
std::stringstream ss;
ss << "rgb(" << r * 255 << "," << g * 255 << "," << b * 255 << ")";
return ss.str();
}
};

class ColorGenerator {
public:
/**
* @brief Add a color to the sources.
*
* @param c the color
* @param weight the force of this source
*/
void addColorSource(const Color &c, const double &weight) {
colors.push_back(c);
weights.push_back(weight);
}

Color makeNewColor() {
// Starting random color
double r = 2, g = 2, b = 2;
double nr = _rd_dist(_rd_engine);
double ng = _rd_dist(_rd_engine);
double nb = _rd_dist(_rd_engine);

// Gradient descend
int k = 0;
double fr, fg, fb;
double ur, ug, ub, norm;
while (std::fabs(Color::distance({r, g, b}, {nr, ng, nb})) > GRADIENT_TOL &&
k < MAX_GRADIENT_ITER) {
// Update rgb
r = nr;
g = ng;
b = nb;

// Compute grad force
fr = 0;
fg = 0;
fb = 0;
for (ulong i = 0; i < colors.size(); i++) {
// Compute direction
ur = (r - colors[i].r);
ug = (g - colors[i].g);
ub = (b - colors[i].b);
norm = ur * ur + ug * ug + ub * ub;

// Compute force
fr += weights[i] * ur / (norm * norm * norm);
fg += weights[i] * ug / (norm * norm * norm);
fb += weights[i] * ub / (norm * norm * norm);
}

nr = std::max(0., std::min(nr + fr * GRADIENT_STEP, 1.));
ng = std::max(0., std::min(ng + fg * GRADIENT_STEP, 1.));
nb = std::max(0., std::min(nb + fb * GRADIENT_STEP, 1.));

k += 1;
}

colors.push_back({nr, ng, nb});
weights.push_back(NEW_COLOR_W);

return Color{nr, ng, nb};
}

// --------------------------------------------------------------------------
// Static methods
// --------------------------------------------------------------------------

/**
* @brief Create a new generator with default sources at corners.
*/
static ColorGenerator basicGenerator() {
ColorGenerator gen;
gen.addColorSource({1, 1, 1}, WHITE_W);
gen.addColorSource({1, 1, 0}, OTHER_W);
gen.addColorSource({1, 0, 1}, OTHER_W);
gen.addColorSource({1, 0, 0}, OTHER_W);
gen.addColorSource({0, 1, 1}, OTHER_W);
gen.addColorSource({0, 1, 0}, OTHER_W);
gen.addColorSource({0, 0, 1}, OTHER_W);
gen.addColorSource({0, 0, 0}, BLACK_W);
return gen;
}

private:
ColorGenerator() {}

// Random generator
std::default_random_engine _rd_engine;
std::uniform_real_distribution<> _rd_dist{0, 1};

// Gradient descent
static constexpr int MAX_GRADIENT_ITER{(int)1E3};
static constexpr double GRADIENT_TOL{1E-5};
static constexpr double GRADIENT_STEP{1E-4};

// Weights
static constexpr double BLACK_W{3};
static constexpr double WHITE_W{0.6};
static constexpr double OTHER_W{0.35};
static constexpr double NEW_COLOR_W{0.2};

std::vector<Color> colors;
std::vector<double> weights;
};

} // namespace kami::color

#endif
2 changes: 1 addition & 1 deletion include/kami/export/line_settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ enum class LineStyle { NONE, PERIMETER, INNER, CUTTED };
inline void appendLineStyle(LineStyle line, std::stringstream &ss) {
switch (line) {
case LineStyle::NONE:
ss << "";
ss << "stroke=\"white\" stroke-width=\"0\"";
break;
case LineStyle::PERIMETER:
ss << "stroke=\"black\" stroke-width=\"3\"";
Expand Down
File renamed without changes.
13 changes: 13 additions & 0 deletions include/kami/export/svg_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@

#include "kami/export/line_settings.hpp"
#include <sstream>
#include <string>
#include <vector>

namespace kami::out::svg {

typedef std::stringstream stream;

// ==========================================================================
// Polyline
// ==========================================================================

/**
* @brief Add a polyline in the given SVG stream
*/
void polyline(stream &, const std::vector<double> &x,
const std::vector<double> &y, const LineStyle &line,
const std::string &fill_color, double opacity = 0.45);

// ==========================================================================
// Line
// ==========================================================================
Expand Down
4 changes: 2 additions & 2 deletions include/kami/global/arguments.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef KAMI_ARGUMENTS
#define KAMI_ARGUMENTS

#include "kami/global/logging.hpp"
#include <cmath>
#include <cstring>
#include <iostream>
Expand All @@ -11,8 +12,7 @@
namespace kami::args {

inline void appHeader() {
std::cout << " --- Kami, a paper pattern maker by Meltwin (2023) ---"
<< std::endl;
printTitle("Kami, a paper pattern maker by Meltwin (2023)");
}

inline void printHelp() {
Expand Down
49 changes: 47 additions & 2 deletions include/kami/global/logging.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,62 @@
#define KAMI_LOGGING

#include <chrono>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <string>
#include <utility>

// ----------------------------------------------------------------------------
// Headers function
// ----------------------------------------------------------------------------

#define TITLE_WIDTH 80
#define TITLE_PAD_CHAR '-'
#define SECTION_WIDTH 60
#define SECTION_PAD_CHAR '='

inline std::pair<int, int> computePadding(int input_width, int output_width) {
return std::pair<int, int>{std::ceil((output_width - input_width) / 2),
std::floor((output_width - input_width) / 2)};
}

inline void printTitle(std::string title) {
auto pair = computePadding(title.length() + 2, TITLE_WIDTH);
std::cout << std::string(pair.first, TITLE_PAD_CHAR) << " " << title << " "
<< std::string(pair.second, TITLE_PAD_CHAR) << std::endl;
}

inline void printSectionHeader(std::string title) {
auto pairI = computePadding(title.length() + 2, SECTION_WIDTH);
auto pairO = computePadding(SECTION_WIDTH, TITLE_WIDTH);
std::cout << std::string(pairO.first, TITLE_PAD_CHAR);
std::cout << std::string(pairI.first, SECTION_PAD_CHAR);
std::cout << " " << title << " ";
std::cout << std::string(pairI.second, SECTION_PAD_CHAR);
std::cout << std::string(pairO.second, TITLE_PAD_CHAR);
std::cout << std::endl;
}

inline void printStepHeader(std::string title) {
std::cout << "====> " << title << std::endl;
}

// ----------------------------------------------------------------------------
// Timing utils
// ----------------------------------------------------------------------------

#define TIMED_UTILS \
std::chrono::system_clock::time_point start; \
std::chrono::system_clock::time_point end;

#define TIMED_SECTION(title, exec) \
std::cout << title << std::endl; \
printSectionHeader(title); \
start = std::chrono::high_resolution_clock::now(); \
exec; \
end = std::chrono::high_resolution_clock::now(); \
std::cout << "\tTook " << (end - start) / std::chrono::milliseconds(1) \
std::cout << std::endl \
<< "\t... Took " << (end - start) / std::chrono::milliseconds(1) \
<< " ms" << std::endl;

#endif
22 changes: 17 additions & 5 deletions include/kami/math/bounds.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,42 @@ namespace kami::math {
struct Bounds {
double xmin, xmax;
double ymin, ymax;
double zmin, zmax;

Bounds()
: xmin(std::numeric_limits<double>::max()),
xmax(std::numeric_limits<double>::min()),
ymin(std::numeric_limits<double>::max()),
ymax(std::numeric_limits<double>::min()) {}
Bounds(double _xmin, double _xmax, double _ymin, double _ymax)
: xmin(_xmin), xmax(_xmax), ymin(_ymin), ymax(_ymax) {}
ymax(std::numeric_limits<double>::min()),
zmin(std::numeric_limits<double>::max()),
zmax(std::numeric_limits<double>::min()) {}
Bounds(double _xmin, double _xmax, double _ymin, double _ymax, double _zmin,
double _zmax)
: xmin(_xmin), xmax(_xmax), ymin(_ymin), ymax(_ymax), zmin(_ymin),
zmax(_ymax) {}

Bounds &operator+=(const Bounds &other) {
// X
if (other.xmin < this->xmin)
this->xmin = other.xmin;
if (other.xmax > this->xmax)
this->xmax = other.xmax;
// Y
if (other.ymin < this->ymin)
this->ymin = other.ymin;
if (other.ymax > this->ymax)
this->ymax = other.ymax;
// Z
if (other.zmin < this->zmin)
this->zmin = other.zmin;
if (other.zmax > this->zmax)
this->zmax = other.zmax;
return *this;
}

friend std::ostream &operator<<(std::ostream &os, const Bounds &b) {
os << "Bound (" << b.xmin << ", " << b.ymin << ", ";
os << b.xmax << ", " << b.ymax << ")";
os << "Bound (" << b.xmin << ", " << b.ymin << ", " << b.zmin << ", ";
os << b.xmax << ", " << b.ymax << ", " << b.zmax << ")";
return os;
}
};
Expand Down
16 changes: 15 additions & 1 deletion include/kami/math/edge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ struct Edge {
const Vertex &getFirst() const { return v1; }
const Vertex &getSecond() const { return v2; }

void setFirst(const Vertex &_v1) { v1 = _v1; }
void setSecond(const Vertex &_v2) { v2 = _v2; }

// ==========================================================================
// Utils for vertex computations
// ==========================================================================
Expand All @@ -40,7 +43,7 @@ struct Edge {
/**
* @brief Return the center of the edge
*/
inline Vertex pos() const { return Vertex::barycenter({v1, v2}); }
inline Vertex pos() const { return v1; }

// ==========================================================================
// Utils for edges computations
Expand Down Expand Up @@ -94,6 +97,17 @@ struct Edge {
*/
static IntersectParams findIntersect(const Edge &e1, const Edge &e2);

static bool colinear(const Vertex &v1, const Vertex &v2) {
return (std::fabs(v1(1) * v2(2) - v1(2) * v2(1)) <= MAX_DISTANCE) &&
(std::fabs(v1(2) * v2(0) - v1(0) * v2(2)) <= MAX_DISTANCE) &&
(std::fabs(v1(0) * v2(1) - v1(1) * v2(0)) <= MAX_DISTANCE);
}

static bool sameDir(const Vertex &v1, const Vertex &v2) {
return colinear(v1, v2) &&
(v1(0) * v2(0) + v1(1) * v2(1) + v1(2) * v2(2) >= 0);
}

protected:
Vertex v1, v2;
};
Expand Down
13 changes: 11 additions & 2 deletions include/kami/math/hmat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,18 @@ struct HMat : public Mat4 {
HMat out;

// Invert rotation
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
double norm;
for (int j = 0; j < 3; j++) {
norm = 0;
for (int i = 0; i < 3; i++) {
out(i, j) = (*this)(j, i);
norm += out(i, j) * out(i, j);
}
norm = std::sqrt(norm);

/*for (int i = 0; i < 3; i++)
out(i, j) /= norm;*/
}

// New translation
for (int i = 0; i < 3; i++)
Expand Down
7 changes: 6 additions & 1 deletion include/kami/math/vertex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "kami/math/base_types.hpp"
#include "microstl/microstl.hpp"
#include <iostream>

namespace kami::math {
/**
Expand Down Expand Up @@ -91,7 +92,11 @@ struct Vertex : public Vec4 {
operator Vec3() const { return Vec3{(*this)(0), (*this)(1), (*this)(2)}; }
};

typedef std::pair<Vertex, Vertex> VertexPair;
struct VertexPair : public std::pair<Vertex, Vertex> {
VertexPair() : std::pair<Vertex, Vertex>(Vertex(0, 0, 0), Vertex(0, 0, 0)) {}
VertexPair(const Vertex &v1, const Vertex &v2)
: std::pair<Vertex, Vertex>(v1, v2) {}
};
} // namespace kami::math

#endif
Loading

0 comments on commit efc2d00

Please sign in to comment.