Commit 450f0481 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

add standard transforms

parent 8ee1c73b
Loading
Loading
Loading
Loading
+92 −2
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@

namespace fviz {

constexpr double TAU = M_PI * 2;

vec2::vec2() :
    x(0.0),
    y(0.0) {}
@@ -29,12 +31,48 @@ vec2::vec2(
    x(_x),
    y(_y) {}

double vec2_magnitude(const vec2& v) {
vec2::vec2(
    const vec3& v) :
    x(v.x),
    y(v.y) {}

vec3::vec3() :
    x(0.0),
    y(0.0),
    z(0.0) {}

vec3::vec3(
    double _x,
    double _y,
    double _z) :
    x(_x),
    y(_y),
    z(_z) {}

vec3::vec3(
    const vec2& v,
    double _z) :
    x(v.x),
    y(v.y),
    z(_z) {}

mat3::mat3() :
    a(0.0),
    b(0.0),
    c(0.0),
    d(0.0),
    e(0.0),
    f(0.0),
    g(0.0),
    h(0.0),
    i(0.0) {}

double magnitude(const vec2& v) {
  return sqrt(v.x * v.x + v.y * v.y);
}

vec2 normalize(const vec2& v) {
  auto m = vec2_magnitude(v);
  auto m = magnitude(v);
  return {v.x / m, v.y / m};
}

@@ -50,6 +88,29 @@ vec2 mul(const vec2& v, double s) {
  return {v.x * s, v.y * s};
}

mat3 mul(const mat3& a, const mat3& b) {
  mat3 m;

  m.a = a.a * b.a + a.b * b.d + a.c * b.g;
  m.b = a.a * b.b + a.b * b.e + a.c * b.h;
  m.c = a.a * b.c + a.b * b.f + a.c * b.i;
  m.d = a.d * b.a + a.e * b.d + a.f * b.g;
  m.e = a.d * b.b + a.e * b.e + a.f * b.h;
  m.f = a.d * b.c + a.e * b.f + a.f * b.i;
  m.g = a.g * b.a + a.h * b.d + a.i * b.g;
  m.h = a.g * b.b + a.h * b.e + a.i * b.h;
  m.i = a.g * b.c + a.h * b.f + a.i * b.i;

  return m;
}

vec3 mul(const mat3& m, const vec3& v) {
  return vec3(
      m.a * v.x + m.b * v.y + m.c * v.z,
      m.d * v.x + m.e * v.y + m.f * v.z,
      m.g * v.x + m.h * v.y + m.i * v.z);
}

double dot(const vec2& a, const vec2& b) {
  return a.x * b.x + a.y * b.y;
}
@@ -69,6 +130,35 @@ vec2 mean(const vec2* v, size_t v_len) {
  return mul(m, 1.0 / v_len);
}

mat3 rotate2(double angle) {
  double angle_tau = (-angle / 360) * TAU;
  mat3 m;
  m.a = cos(angle_tau);
  m.b = sin(angle_tau) * -1;
  m.d = sin(angle_tau);
  m.e = cos(angle_tau);
  m.i = 1.0;
  return m;
}

mat3 scale2(const vec2& s) {
  mat3 m;
  m.a = s.x;
  m.e = s.y;
  m.i = 1.0;
  return m;
}

mat3 translate2(const vec2& t) {
  mat3 m;
  m.a = 1.0;
  m.e = 1.0;
  m.i = 1.0;
  m.c = t.x;
  m.f = t.y;
  return m;
}

void sort_cw(vec2* v, size_t v_len) {
  auto m = mean(v, v_len);

+68 −0
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@
#include <iostream>

namespace fviz {
struct vec2;
struct vec3;


/**
 * A two-dimensional vector of the following form:
@@ -29,8 +32,47 @@ namespace fviz {
struct vec2 {
  vec2();
  vec2(double x, double y);
  explicit vec2(const vec3& v);
  double x;
  double y;
};

/**
 * A three-dimensional vector of the following form:
 *
 *   | X |
 *   | Y |
 *   | Z |
 *
 */
struct vec3 {
  vec3();
  vec3(double x, double y, double z);
  vec3(const vec2& v, double z);
  double x;
  double y;
  double z;
};

/**
 * A 3x3 matrix of the following form:
 *
 *   | A B C |
 *   | D E F |
 *   | G H I |
 *
 */
struct mat3 {
  mat3();
  double a;
  double d;
  double g;
  double b;
  double e;
  double h;
  double c;
  double f;
  double i;
};

/**
@@ -48,6 +90,16 @@ vec2 sub(const vec2& a, const vec2& b);
 */
vec2 mul(const vec2& v, double s);

/**
 * Multiply a 3x3 matrix with a 3x3 matrix
 */
mat3 mul(const mat3& a, const mat3& b);

/**
 * Multiply a 3x3 matrix with a three-dimensional vector
 */
vec3 mul(const mat3& m, const vec3& v);

/**
 * Compute the dot (scalar) product of two vectors
 */
@@ -75,6 +127,22 @@ vec2 normalize(const vec2& v);
 */
vec2 mean(const vec2* v, size_t v_len);

/**
 * Create a 2D "rotation matrix" that rotates `angle` degrees clockwise around
 * origin
 */
mat3 rotate2(double angle);

/**
 * Create a 2D "scale matrix"
 */
mat3 scale2(const vec2& s);

/**
 * Create a 2D "translation matrix"
 */
mat3 translate2(const vec2& t);

/**
 * Sort an array of vec2 objects in clockwise order
 */
+79 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "fviz" project
 *   Copyright (c) 2018 Paul Asmuth
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "graphics/brush.h"
#include "graphics/color.h"
#include "graphics/page_description.h"
#include "graphics/text.h"
#include "environment.h"
#include "utils/fileutil.h"
#include "unittest.h"

using namespace fviz;

void test_translate() {
  auto m = translate2({1.0, 1.0});
  auto v1 = vec3(5.0, 2.0, 1.0);
  auto v2 = mul(m, v1);
  EXPECT_FEQ(v2.x, 6.0);
  EXPECT_FEQ(v2.y, 3.0);
}

void test_scale() {
  auto m = scale2({3.0, 3.0});
  auto v1 = vec3(5.0, 2.0, 1.0);
  auto v2 = mul(m, v1);
  EXPECT_FEQ(v2.x, 15.0);
  EXPECT_FEQ(v2.y, 6.0);
}

void test_rotate() {
  {
    auto m = rotate2(90);
    auto v1 = vec3(0.0, 2.0, 1.0);
    auto v2 = mul(m, v1);
    EXPECT_FEQ(v2.x, 2.0);
    EXPECT_FEQ(v2.y, 0.0);
  }

  {
    auto m = rotate2(180);
    auto v1 = vec3(0.0, 2.0, 1.0);
    auto v2 = mul(m, v1);
    EXPECT_FEQ(v2.x, 0.0);
    EXPECT_FEQ(v2.y, -2.0);
  }

  {
    auto m = rotate2(270);
    auto v1 = vec3(0.0, 2.0, 1.0);
    auto v2 = mul(m, v1);
    EXPECT_FEQ(v2.x, -2.0);
    EXPECT_FEQ(v2.y, 0.0);
  }

  {
    auto m = rotate2(360);
    auto v1 = vec3(0.0, 2.0, 1.0);
    auto v2 = mul(m, v1);
    EXPECT_FEQ(v2.x, 0.0);
    EXPECT_FEQ(v2.y, 2.0);
  }
}

int main(int argc, char** argv) {
  test_translate();
  test_scale();
  test_rotate();
}