TraceMaker
C++ API of the engine
Loading...
Searching...
No Matches
point.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2#pragma once
3// Integer-nanometre points and KiCad-compatible rotation.
4#include <cmath>
5#include <cstdint>
6#include <numbers>
7
8#include "core/hd.hpp"
9#include "core/units.hpp"
10
11namespace tmk::geom {
12
13struct Point {
14 Coord x = 0, y = 0;
15 TM_HD friend constexpr Point operator+(Point a, Point b) { return {a.x + b.x, a.y + b.y}; }
16 TM_HD friend constexpr Point operator-(Point a, Point b) { return {a.x - b.x, a.y - b.y}; }
17 TM_HD friend constexpr bool operator==(Point a, Point b) { return a.x == b.x && a.y == b.y; }
18};
19
20struct Box {
21 Coord x0 = 0, y0 = 0, x1 = -1, y1 = -1; // empty when x1 < x0
22 constexpr bool empty() const { return x1 < x0 || y1 < y0; }
23 constexpr void add(Point p) {
24 if (empty()) { x0 = x1 = p.x; y0 = y1 = p.y; return; }
25 if (p.x < x0) x0 = p.x;
26 if (p.x > x1) x1 = p.x;
27 if (p.y < y0) y0 = p.y;
28 if (p.y > y1) y1 = p.y;
29 }
30 constexpr void add(const Box& b) {
31 if (b.empty()) return;
32 add(Point{b.x0, b.y0});
33 add(Point{b.x1, b.y1});
34 }
35 constexpr Box inflated(Coord d) const { return empty() ? *this : Box{x0 - d, y0 - d, x1 + d, y1 + d}; }
36 constexpr bool intersects(const Box& b) const { return !(b.x0 > x1 || b.x1 < x0 || b.y0 > y1 || b.y1 < y0); }
37};
38
39// Rounds half away from zero, like KiCad's KiROUND.
40inline Coord kiround(double v) { return static_cast<Coord>(v < 0 ? v - 0.5 : v + 0.5); }
41
42// Normalises degrees to [0, 360).
43inline double norm_deg(double a) {
44 a = std::fmod(a, 360.0);
45 if (a < 0) a += 360.0;
46 if (a >= 360.0) a -= 360.0;
47 return a;
48}
49
50// Rotates p by `deg` degrees the way KiCad does: positive angles turn counter-clockwise on screen in KiCad's
51// y-down coordinates. Multiples of 90° are exact.
52inline Point rotate(Point p, double deg) {
53 const double a = norm_deg(deg);
54 if (a == 0.0) return p;
55 if (a == 90.0) return {p.y, -p.x};
56 if (a == 180.0) return {-p.x, -p.y};
57 if (a == 270.0) return {-p.y, p.x};
58 const double r = a * std::numbers::pi / 180.0;
59 const double c = std::cos(r), s = std::sin(r);
60 const double x = static_cast<double>(p.x), y = static_cast<double>(p.y);
61 return {kiround(x * c + y * s), kiround(-x * s + y * c)};
62}
63
64} // namespace tmk::geom
TM_HD marks functions that must compile identically for host and device.
#define TM_HD
Definition hd.hpp:9
Point rotate(Point p, double deg)
Rotates p by deg degrees the way KiCad does: positive angles turn counter-clockwise on screen in KiCa...
Definition point.hpp:52
Coord kiround(double v)
Rounds half away from zero, like KiCad's KiROUND.
Definition point.hpp:40
double norm_deg(double a)
Normalises degrees to [0, 360).
Definition point.hpp:43
std::int64_t Coord
Engine coordinate: signed 64-bit nanometres.
Definition units.hpp:12
constexpr Box inflated(Coord d) const
Definition point.hpp:35
constexpr void add(const Box &b)
Definition point.hpp:30
Coord y1
empty when x1 < x0
Definition point.hpp:21
constexpr bool empty() const
Definition point.hpp:22
constexpr void add(Point p)
Definition point.hpp:23
constexpr bool intersects(const Box &b) const
Definition point.hpp:36
TM_HD friend constexpr Point operator+(Point a, Point b)
Definition point.hpp:15
TM_HD friend constexpr Point operator-(Point a, Point b)
Definition point.hpp:16
TM_HD friend constexpr bool operator==(Point a, Point b)
Definition point.hpp:17