mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2024-11-24 13:15:01 +00:00
4ef02fd699
Removes the TTL triangulator in favor of the delaunator triangulator. This removes the only AGPL code in the KiCad codebase and therefore allows the full project to be licensed under the GPLv3.
148 lines
3.5 KiB
C++
148 lines
3.5 KiB
C++
#pragma once
|
|
|
|
#ifdef DELAUNATOR_HEADER_ONLY
|
|
#define INLINE inline
|
|
#else
|
|
#define INLINE
|
|
#endif
|
|
|
|
#include <limits>
|
|
#include <vector>
|
|
#include <ostream>
|
|
|
|
namespace delaunator {
|
|
|
|
constexpr std::size_t INVALID_INDEX =
|
|
(std::numeric_limits<std::size_t>::max)();
|
|
|
|
class Point
|
|
{
|
|
public:
|
|
Point(double x, double y) : m_x(x), m_y(y)
|
|
{}
|
|
Point() : m_x(0), m_y(0)
|
|
{}
|
|
|
|
double x() const
|
|
{ return m_x; }
|
|
|
|
double y() const
|
|
{ return m_y; }
|
|
|
|
double magnitude2() const
|
|
{ return m_x * m_x + m_y * m_y; }
|
|
|
|
static double determinant(const Point& p1, const Point& p2)
|
|
{
|
|
return p1.m_x * p2.m_y - p1.m_y * p2.m_x;
|
|
}
|
|
|
|
static Point vector(const Point& p1, const Point& p2)
|
|
{
|
|
return Point(p2.m_x - p1.m_x, p2.m_y - p1.m_y);
|
|
}
|
|
|
|
static double dist2(const Point& p1, const Point& p2)
|
|
{
|
|
Point vec = vector(p1, p2);
|
|
return vec.m_x * vec.m_x + vec.m_y * vec.m_y;
|
|
}
|
|
|
|
static bool equal(const Point& p1, const Point& p2, double span)
|
|
{
|
|
double dist = dist2(p1, p2) / span;
|
|
|
|
// ABELL - This number should be examined to figure how how
|
|
// it correlates with the breakdown of calculating determinants.
|
|
return dist < 1e-20;
|
|
}
|
|
|
|
private:
|
|
double m_x;
|
|
double m_y;
|
|
};
|
|
|
|
inline std::ostream& operator<<(std::ostream& out, const Point& p)
|
|
{
|
|
out << p.x() << "/" << p.y();
|
|
return out;
|
|
}
|
|
|
|
|
|
class Points
|
|
{
|
|
public:
|
|
using const_iterator = Point const *;
|
|
|
|
Points(const std::vector<double>& coords) : m_coords(coords)
|
|
{}
|
|
|
|
const Point& operator[](size_t offset)
|
|
{
|
|
return reinterpret_cast<const Point&>(
|
|
*(m_coords.data() + (offset * 2)));
|
|
};
|
|
|
|
Points::const_iterator begin() const
|
|
{ return reinterpret_cast<const Point *>(m_coords.data()); }
|
|
Points::const_iterator end() const
|
|
{ return reinterpret_cast<const Point *>(
|
|
m_coords.data() + m_coords.size()); }
|
|
size_t size() const
|
|
{ return m_coords.size() / 2; }
|
|
|
|
private:
|
|
const std::vector<double>& m_coords;
|
|
};
|
|
|
|
class Delaunator {
|
|
|
|
public:
|
|
std::vector<double> const& coords;
|
|
Points m_points;
|
|
|
|
// 'triangles' stores the indices to the 'X's of the input
|
|
// 'coords'.
|
|
std::vector<std::size_t> triangles;
|
|
|
|
// 'halfedges' store indices into 'triangles'. If halfedges[X] = Y,
|
|
// It says that there's an edge from X to Y where a) X and Y are
|
|
// both indices into triangles and b) X and Y are indices into different
|
|
// triangles in the array. This allows you to get from a triangle to
|
|
// its adjacent triangle. If the a triangle edge has no adjacent triangle,
|
|
// its half edge will be INVALID_INDEX.
|
|
std::vector<std::size_t> halfedges;
|
|
|
|
std::vector<std::size_t> hull_prev;
|
|
std::vector<std::size_t> hull_next;
|
|
|
|
// This contains indexes into the triangles array.
|
|
std::vector<std::size_t> hull_tri;
|
|
std::size_t hull_start;
|
|
|
|
INLINE Delaunator(std::vector<double> const& in_coords);
|
|
INLINE double get_hull_area();
|
|
INLINE double get_triangle_area();
|
|
|
|
private:
|
|
std::vector<std::size_t> m_hash;
|
|
Point m_center;
|
|
std::size_t m_hash_size;
|
|
std::vector<std::size_t> m_edge_stack;
|
|
|
|
INLINE std::size_t legalize(std::size_t a);
|
|
INLINE std::size_t hash_key(double x, double y) const;
|
|
INLINE std::size_t add_triangle(
|
|
std::size_t i0,
|
|
std::size_t i1,
|
|
std::size_t i2,
|
|
std::size_t a,
|
|
std::size_t b,
|
|
std::size_t c);
|
|
INLINE void link(std::size_t a, std::size_t b);
|
|
};
|
|
|
|
} //namespace delaunator
|
|
|
|
#undef INLINE
|