Cleanup: Use math vector types in delaunay triangulation code
Rather than defining a separate vector type just for use here.
This commit is contained in:
@@ -73,20 +73,6 @@ enum CDT_output_type {
|
||||
|
||||
namespace blender::meshintersect {
|
||||
|
||||
/** #vec2<Arith_t> is a 2d vector with #Arith_t as the type for coordinates. */
|
||||
template<typename Arith_t> struct vec2_impl;
|
||||
template<> struct vec2_impl<double> {
|
||||
typedef double2 type;
|
||||
};
|
||||
|
||||
#ifdef WITH_GMP
|
||||
template<> struct vec2_impl<mpq_class> {
|
||||
typedef mpq2 type;
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename Arith_t> using vec2 = typename vec2_impl<Arith_t>::type;
|
||||
|
||||
/**
|
||||
* Input to Constrained Delaunay Triangulation.
|
||||
* Input vertex coordinates are stored in `vert`. For the rest of the input,
|
||||
@@ -137,12 +123,12 @@ template<typename Arith_t> using vec2 = typename vec2_impl<Arith_t>::type;
|
||||
* If this is not needed, set need_ids to false and the execution may be much
|
||||
* faster in some circumstances.
|
||||
*/
|
||||
template<typename Arith_t> class CDT_input {
|
||||
template<typename T> class CDT_input {
|
||||
public:
|
||||
Array<vec2<Arith_t>> vert;
|
||||
Array<VecBase<T, 2>> vert;
|
||||
Array<std::pair<int, int>> edge;
|
||||
Array<Vector<int>> face;
|
||||
Arith_t epsilon{0};
|
||||
T epsilon{0};
|
||||
bool need_ids{true};
|
||||
};
|
||||
|
||||
@@ -168,9 +154,9 @@ template<typename Arith_t> class CDT_input {
|
||||
* edge is part of a given output edge. See the comment below for how
|
||||
* to decode the entries in the edge_orig table.
|
||||
*/
|
||||
template<typename Arith_t> class CDT_result {
|
||||
template<typename T> class CDT_result {
|
||||
public:
|
||||
Array<vec2<Arith_t>> vert;
|
||||
Array<VecBase<T, 2>> vert;
|
||||
Array<std::pair<int, int>> edge;
|
||||
Array<Vector<int>> face;
|
||||
/* The orig vectors are only populated if the need_ids input field is true. */
|
||||
|
||||
@@ -76,21 +76,21 @@ template<> double math_to_double<double>(const double v)
|
||||
* While this could be cleaned up some, it is usable by other routines in Blender
|
||||
* that need to keep track of a 2D arrangement, with topology.
|
||||
*/
|
||||
template<typename Arith_t> struct CDTVert;
|
||||
template<typename Arith_t> struct CDTEdge;
|
||||
template<typename Arith_t> struct CDTFace;
|
||||
template<typename T> struct CDTVert;
|
||||
template<typename T> struct CDTEdge;
|
||||
template<typename T> struct CDTFace;
|
||||
|
||||
template<typename Arith_t> struct SymEdge {
|
||||
template<typename T> struct SymEdge {
|
||||
/** Next #SymEdge in face, doing CCW traversal of face. */
|
||||
SymEdge<Arith_t> *next{nullptr};
|
||||
SymEdge<T> *next{nullptr};
|
||||
/** Next #SymEdge CCW around vert. */
|
||||
SymEdge<Arith_t> *rot{nullptr};
|
||||
SymEdge<T> *rot{nullptr};
|
||||
/** Vert at origin. */
|
||||
CDTVert<Arith_t> *vert{nullptr};
|
||||
CDTVert<T> *vert{nullptr};
|
||||
/** Un-directed edge this is for. */
|
||||
CDTEdge<Arith_t> *edge{nullptr};
|
||||
CDTEdge<T> *edge{nullptr};
|
||||
/** Face on left side. */
|
||||
CDTFace<Arith_t> *face{nullptr};
|
||||
CDTFace<T> *face{nullptr};
|
||||
|
||||
SymEdge() = default;
|
||||
};
|
||||
@@ -112,67 +112,62 @@ template<typename T> inline SymEdge<T> *prev(const SymEdge<T> *se)
|
||||
/** A coordinate class with extra information for fast filtered orient tests. */
|
||||
|
||||
template<typename T> struct FatCo {
|
||||
vec2<T> exact;
|
||||
vec2<double> approx;
|
||||
vec2<double> abs_approx;
|
||||
VecBase<T, 2> exact;
|
||||
double2 approx;
|
||||
double2 abs_approx;
|
||||
|
||||
FatCo();
|
||||
#ifdef WITH_GMP
|
||||
FatCo(const vec2<mpq_class> &v);
|
||||
FatCo(const mpq2 &v);
|
||||
#endif
|
||||
FatCo(const vec2<double> &v);
|
||||
FatCo(const double2 &v);
|
||||
};
|
||||
|
||||
#ifdef WITH_GMP
|
||||
template<> struct FatCo<mpq_class> {
|
||||
vec2<mpq_class> exact;
|
||||
vec2<double> approx;
|
||||
vec2<double> abs_approx;
|
||||
mpq2 exact;
|
||||
double2 approx;
|
||||
double2 abs_approx;
|
||||
|
||||
FatCo()
|
||||
: exact(vec2<mpq_class>(0, 0)), approx(vec2<double>(0, 0)), abs_approx(vec2<double>(0, 0))
|
||||
{
|
||||
}
|
||||
FatCo() : exact(mpq2(0, 0)), approx(double2(0, 0)), abs_approx(double2(0, 0)) {}
|
||||
|
||||
FatCo(const vec2<mpq_class> &v)
|
||||
FatCo(const mpq2 &v)
|
||||
{
|
||||
exact = v;
|
||||
approx = vec2<double>(v.x.get_d(), v.y.get_d());
|
||||
abs_approx = vec2<double>(fabs(approx.x), fabs(approx.y));
|
||||
approx = double2(v.x.get_d(), v.y.get_d());
|
||||
abs_approx = double2(fabs(approx.x), fabs(approx.y));
|
||||
}
|
||||
|
||||
FatCo(const vec2<double> &v)
|
||||
FatCo(const double2 &v)
|
||||
{
|
||||
exact = vec2<mpq_class>(v.x, v.y);
|
||||
exact = mpq2(v.x, v.y);
|
||||
approx = v;
|
||||
abs_approx = vec2<double>(fabs(approx.x), fabs(approx.y));
|
||||
abs_approx = double2(fabs(approx.x), fabs(approx.y));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<> struct FatCo<double> {
|
||||
vec2<double> exact;
|
||||
vec2<double> approx;
|
||||
vec2<double> abs_approx;
|
||||
double2 exact;
|
||||
double2 approx;
|
||||
double2 abs_approx;
|
||||
|
||||
FatCo() : exact(vec2<double>(0, 0)), approx(vec2<double>(0, 0)), abs_approx(vec2<double>(0, 0))
|
||||
{
|
||||
}
|
||||
FatCo() : exact(double2(0, 0)), approx(double2(0, 0)), abs_approx(double2(0, 0)) {}
|
||||
|
||||
#ifdef WITH_GMP
|
||||
FatCo(const vec2<mpq_class> &v)
|
||||
FatCo(const mpq2 &v)
|
||||
{
|
||||
exact = vec2<double>(v.x.get_d(), v.y.get_d());
|
||||
exact = double2(v.x.get_d(), v.y.get_d());
|
||||
approx = exact;
|
||||
abs_approx = vec2<double>(fabs(approx.x), fabs(approx.y));
|
||||
abs_approx = double2(fabs(approx.x), fabs(approx.y));
|
||||
}
|
||||
#endif
|
||||
|
||||
FatCo(const vec2<double> &v)
|
||||
FatCo(const double2 &v)
|
||||
{
|
||||
exact = v;
|
||||
approx = v;
|
||||
abs_approx = vec2<double>(fabs(approx.x), fabs(approx.y));
|
||||
abs_approx = double2(fabs(approx.x), fabs(approx.y));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -197,23 +192,23 @@ template<typename T> struct CDTVert {
|
||||
int visit_index{0};
|
||||
|
||||
CDTVert() = default;
|
||||
explicit CDTVert(const vec2<T> &pt);
|
||||
explicit CDTVert(const VecBase<T, 2> &pt);
|
||||
};
|
||||
|
||||
template<typename Arith_t> struct CDTEdge {
|
||||
template<typename T> struct CDTEdge {
|
||||
/** Set of input edge ids that this is part of.
|
||||
* If don't need_ids, then should contain 0 if it is a constrained edge,
|
||||
* else empty. */
|
||||
blender::Set<int> input_ids;
|
||||
/** The directed edges for this edge. */
|
||||
SymEdge<Arith_t> symedges[2]{SymEdge<Arith_t>(), SymEdge<Arith_t>()};
|
||||
SymEdge<T> symedges[2]{SymEdge<T>(), SymEdge<T>()};
|
||||
|
||||
CDTEdge() = default;
|
||||
};
|
||||
|
||||
template<typename Arith_t> struct CDTFace {
|
||||
template<typename T> struct CDTFace {
|
||||
/** A symedge in face; only used during output, so only valid then. */
|
||||
SymEdge<Arith_t> *symedge{nullptr};
|
||||
SymEdge<T> *symedge{nullptr};
|
||||
/** Set of input face ids that this is part of.
|
||||
* If don't need_ids, then should contain 0 if it is part of a constrained face,
|
||||
* else empty. */
|
||||
@@ -228,19 +223,19 @@ template<typename Arith_t> struct CDTFace {
|
||||
CDTFace() = default;
|
||||
};
|
||||
|
||||
template<typename Arith_t> struct CDTArrangement {
|
||||
template<typename T> struct CDTArrangement {
|
||||
/* The arrangement owns the memory pointed to by the pointers in these vectors.
|
||||
* They are pointers instead of actual structures because these vectors may be resized and
|
||||
* other elements refer to the elements by pointer. */
|
||||
|
||||
/** The verts. Some may be merged to others (see their merge_to_index). */
|
||||
Vector<CDTVert<Arith_t> *> verts;
|
||||
Vector<CDTVert<T> *> verts;
|
||||
/** The edges. Some may be deleted (SymEdge next and rot pointers are null). */
|
||||
Vector<CDTEdge<Arith_t> *> edges;
|
||||
Vector<CDTEdge<T> *> edges;
|
||||
/** The faces. Some may be deleted (see their delete member). */
|
||||
Vector<CDTFace<Arith_t> *> faces;
|
||||
Vector<CDTFace<T> *> faces;
|
||||
/** Which CDTFace is the outer face. */
|
||||
CDTFace<Arith_t> *outer_face{nullptr};
|
||||
CDTFace<T> *outer_face{nullptr};
|
||||
|
||||
CDTArrangement() = default;
|
||||
~CDTArrangement();
|
||||
@@ -253,7 +248,7 @@ template<typename Arith_t> struct CDTArrangement {
|
||||
* Add a new vertex to the arrangement, with the given 2D coordinate.
|
||||
* It will not be connected to anything yet.
|
||||
*/
|
||||
CDTVert<Arith_t> *add_vert(const vec2<Arith_t> &pt);
|
||||
CDTVert<T> *add_vert(const VecBase<T, 2> &pt);
|
||||
|
||||
/**
|
||||
* Add an edge from v1 to v2. The edge will have a left face and a right face,
|
||||
@@ -261,19 +256,16 @@ template<typename Arith_t> struct CDTArrangement {
|
||||
* If the vertices do not yet have a #SymEdge pointer,
|
||||
* their pointer is set to the #SymEdge in this new edge.
|
||||
*/
|
||||
CDTEdge<Arith_t> *add_edge(CDTVert<Arith_t> *v1,
|
||||
CDTVert<Arith_t> *v2,
|
||||
CDTFace<Arith_t> *fleft,
|
||||
CDTFace<Arith_t> *fright);
|
||||
CDTEdge<T> *add_edge(CDTVert<T> *v1, CDTVert<T> *v2, CDTFace<T> *fleft, CDTFace<T> *fright);
|
||||
|
||||
/**
|
||||
* Add a new face. It is disconnected until an add_edge makes it the
|
||||
* left or right face of an edge.
|
||||
*/
|
||||
CDTFace<Arith_t> *add_face();
|
||||
CDTFace<T> *add_face();
|
||||
|
||||
/** Make a new edge from v to se->vert, splicing it in. */
|
||||
CDTEdge<Arith_t> *add_vert_to_symedge_edge(CDTVert<Arith_t> *v, SymEdge<Arith_t> *se);
|
||||
CDTEdge<T> *add_vert_to_symedge_edge(CDTVert<T> *v, SymEdge<T> *se);
|
||||
|
||||
/**
|
||||
* Assuming s1 and s2 are both #SymEdge's in a face with > 3 sides and one is not the next of the
|
||||
@@ -281,34 +273,34 @@ template<typename Arith_t> struct CDTArrangement {
|
||||
* be the one that s1 has as left face, and a new face will be added and made s2 and its
|
||||
* next-cycle's left face.
|
||||
*/
|
||||
CDTEdge<Arith_t> *add_diagonal(SymEdge<Arith_t> *s1, SymEdge<Arith_t> *s2);
|
||||
CDTEdge<T> *add_diagonal(SymEdge<T> *s1, SymEdge<T> *s2);
|
||||
|
||||
/**
|
||||
* Connect the verts of se1 and se2, assuming that currently those two #SymEdge's are on the
|
||||
* outer boundary (have face == outer_face) of two components that are isolated from each other.
|
||||
*/
|
||||
CDTEdge<Arith_t> *connect_separate_parts(SymEdge<Arith_t> *se1, SymEdge<Arith_t> *se2);
|
||||
CDTEdge<T> *connect_separate_parts(SymEdge<T> *se1, SymEdge<T> *se2);
|
||||
|
||||
/**
|
||||
* Split se at fraction lambda, and return the new #CDTEdge that is the new second half.
|
||||
* Copy the edge input_ids into the new one.
|
||||
*/
|
||||
CDTEdge<Arith_t> *split_edge(SymEdge<Arith_t> *se, Arith_t lambda);
|
||||
CDTEdge<T> *split_edge(SymEdge<T> *se, T lambda);
|
||||
|
||||
/**
|
||||
* Delete an edge. The new combined face on either side of the deleted edge will be the one that
|
||||
* was e's face. There will now be an unused face, which will be marked deleted, and an unused
|
||||
* #CDTEdge, marked by setting the next and rot pointers of its #SymEdge's to #nullptr.
|
||||
*/
|
||||
void delete_edge(SymEdge<Arith_t> *se);
|
||||
void delete_edge(SymEdge<T> *se);
|
||||
|
||||
/**
|
||||
* If the vertex with index i in the vert array has not been merge, return it.
|
||||
* Else return the one that it has merged to.
|
||||
*/
|
||||
CDTVert<Arith_t> *get_vert_resolve_merge(int i)
|
||||
CDTVert<T> *get_vert_resolve_merge(int i)
|
||||
{
|
||||
CDTVert<Arith_t> *v = this->verts[i];
|
||||
CDTVert<T> *v = this->verts[i];
|
||||
if (v->merge_to_index != -1) {
|
||||
v = this->verts[v->merge_to_index];
|
||||
}
|
||||
@@ -499,18 +491,10 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen
|
||||
if (cdt.verts.is_empty()) {
|
||||
return;
|
||||
}
|
||||
vec2<double> vmin(DBL_MAX, DBL_MAX);
|
||||
vec2<double> vmax(-DBL_MAX, -DBL_MAX);
|
||||
double2 vmin(std::numeric_limits<double>::max());
|
||||
double2 vmax(std::numeric_limits<double>::lowest());
|
||||
for (const CDTVert<T> *v : cdt.verts) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
double dvi = v->co.approx[i];
|
||||
if (dvi < vmin[i]) {
|
||||
vmin[i] = dvi;
|
||||
}
|
||||
if (dvi > vmax[i]) {
|
||||
vmax[i] = dvi;
|
||||
}
|
||||
}
|
||||
math::min_max(v->co.approx, vmin, vmax);
|
||||
}
|
||||
double draw_margin = ((vmax.x - vmin.x) + (vmax.y - vmin.y)) * margin_expand;
|
||||
double minx = vmin.x - draw_margin;
|
||||
@@ -557,8 +541,8 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen
|
||||
}
|
||||
const CDTVert<T> *u = e->symedges[0].vert;
|
||||
const CDTVert<T> *v = e->symedges[1].vert;
|
||||
const vec2<double> &uco = u->co.approx;
|
||||
const vec2<double> &vco = v->co.approx;
|
||||
const double2 &uco = u->co.approx;
|
||||
const double2 &vco = v->co.approx;
|
||||
int strokew = e->input_ids.size() == 0 ? thin_line : thick_line;
|
||||
f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\""
|
||||
<< SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\""
|
||||
@@ -603,7 +587,7 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen
|
||||
if (se_face_start != nullptr) {
|
||||
/* Find center of face. */
|
||||
int face_nverts = 0;
|
||||
vec2<double> cen(0.0, 0.0);
|
||||
double2 cen(0.0, 0.0);
|
||||
if (face == cdt.outer_face) {
|
||||
cen.x = minx;
|
||||
cen.y = miny;
|
||||
@@ -756,12 +740,12 @@ bool in_line<mpq_class>(const FatCo<mpq_class> &a,
|
||||
const FatCo<mpq_class> &b,
|
||||
const FatCo<mpq_class> &c)
|
||||
{
|
||||
vec2<double> ab = b.approx - a.approx;
|
||||
vec2<double> bc = c.approx - b.approx;
|
||||
vec2<double> ac = c.approx - a.approx;
|
||||
vec2<double> supremum_ab = b.abs_approx + a.abs_approx;
|
||||
vec2<double> supremum_bc = c.abs_approx + b.abs_approx;
|
||||
vec2<double> supremum_ac = c.abs_approx + a.abs_approx;
|
||||
double2 ab = b.approx - a.approx;
|
||||
double2 bc = c.approx - b.approx;
|
||||
double2 ac = c.approx - a.approx;
|
||||
double2 supremum_ab = b.abs_approx + a.abs_approx;
|
||||
double2 supremum_bc = c.abs_approx + b.abs_approx;
|
||||
double2 supremum_ac = c.abs_approx + a.abs_approx;
|
||||
double dot_ab_ac = ab.x * ac.x + ab.y * ac.y;
|
||||
double supremum_dot_ab_ac = supremum_ab.x * supremum_ac.x + supremum_ab.y * supremum_ac.y;
|
||||
constexpr double index = 6;
|
||||
@@ -775,12 +759,12 @@ bool in_line<mpq_class>(const FatCo<mpq_class> &a,
|
||||
if (dot_bc_ac < -err_bound) {
|
||||
return false;
|
||||
}
|
||||
vec2<mpq_class> exact_ab = b.exact - a.exact;
|
||||
vec2<mpq_class> exact_ac = c.exact - a.exact;
|
||||
mpq2 exact_ab = b.exact - a.exact;
|
||||
mpq2 exact_ac = c.exact - a.exact;
|
||||
if (dot(exact_ab, exact_ac) < 0) {
|
||||
return false;
|
||||
}
|
||||
vec2<mpq_class> exact_bc = c.exact - b.exact;
|
||||
mpq2 exact_bc = c.exact - b.exact;
|
||||
return dot(exact_bc, exact_ac) >= 0;
|
||||
}
|
||||
#endif
|
||||
@@ -788,16 +772,16 @@ bool in_line<mpq_class>(const FatCo<mpq_class> &a,
|
||||
template<>
|
||||
bool in_line<double>(const FatCo<double> &a, const FatCo<double> &b, const FatCo<double> &c)
|
||||
{
|
||||
vec2<double> ab = b.approx - a.approx;
|
||||
vec2<double> ac = c.approx - a.approx;
|
||||
double2 ab = b.approx - a.approx;
|
||||
double2 ac = c.approx - a.approx;
|
||||
if (dot(ab, ac) < 0) {
|
||||
return false;
|
||||
}
|
||||
vec2<double> bc = c.approx - b.approx;
|
||||
double2 bc = c.approx - b.approx;
|
||||
return dot(bc, ac) >= 0;
|
||||
}
|
||||
|
||||
template<> CDTVert<double>::CDTVert(const vec2<double> &pt)
|
||||
template<> CDTVert<double>::CDTVert(const double2 &pt)
|
||||
{
|
||||
this->co.exact = pt;
|
||||
this->co.approx = pt;
|
||||
@@ -809,7 +793,7 @@ template<> CDTVert<double>::CDTVert(const vec2<double> &pt)
|
||||
}
|
||||
|
||||
#ifdef WITH_GMP
|
||||
template<> CDTVert<mpq_class>::CDTVert(const vec2<mpq_class> &pt)
|
||||
template<> CDTVert<mpq_class>::CDTVert(const mpq2 &pt)
|
||||
{
|
||||
this->co.exact = pt;
|
||||
this->co.approx = double2(pt.x.get_d(), pt.y.get_d());
|
||||
@@ -821,7 +805,7 @@ template<> CDTVert<mpq_class>::CDTVert(const vec2<mpq_class> &pt)
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T> CDTVert<T> *CDTArrangement<T>::add_vert(const vec2<T> &pt)
|
||||
template<typename T> CDTVert<T> *CDTArrangement<T>::add_vert(const VecBase<T, 2> &pt)
|
||||
{
|
||||
CDTVert<T> *v = new CDTVert<T>(pt);
|
||||
int index = this->verts.append_and_get_index(v);
|
||||
@@ -1064,8 +1048,8 @@ CDTEdge<T> *CDTArrangement<T>::connect_separate_parts(SymEdge<T> *se1, SymEdge<T
|
||||
template<typename T> CDTEdge<T> *CDTArrangement<T>::split_edge(SymEdge<T> *se, T lambda)
|
||||
{
|
||||
/* Split e at lambda. */
|
||||
const vec2<T> *a = &se->vert->co.exact;
|
||||
const vec2<T> *b = &se->next->vert->co.exact;
|
||||
const VecBase<T, 2> *a = &se->vert->co.exact;
|
||||
const VecBase<T, 2> *b = &se->next->vert->co.exact;
|
||||
SymEdge<T> *sesym = sym(se);
|
||||
SymEdge<T> *sesymprev = prev(sesym);
|
||||
SymEdge<T> *sesymprevsym = sym(sesymprev);
|
||||
@@ -1177,8 +1161,8 @@ template<typename T> class SiteInfo {
|
||||
*/
|
||||
template<typename T> bool site_lexicographic_sort(const SiteInfo<T> &a, const SiteInfo<T> &b)
|
||||
{
|
||||
const vec2<T> &co_a = a.v->co.exact;
|
||||
const vec2<T> &co_b = b.v->co.exact;
|
||||
const VecBase<T, 2> &co_a = a.v->co.exact;
|
||||
const VecBase<T, 2> &co_b = b.v->co.exact;
|
||||
if (co_a[0] < co_b[0]) {
|
||||
return true;
|
||||
}
|
||||
@@ -1697,7 +1681,7 @@ void fill_crossdata_for_intersect(const FatCo<T> &curco,
|
||||
auto isect = isect_seg_seg(va->co.exact, vb->co.exact, curco.exact, v2->co.exact);
|
||||
T &lambda = isect.lambda;
|
||||
switch (isect.kind) {
|
||||
case isect_result<vec2<T>>::LINE_LINE_CROSS: {
|
||||
case isect_result<VecBase<T, 2>>::LINE_LINE_CROSS: {
|
||||
#ifdef WITH_GMP
|
||||
if (!std::is_same<T, mpq_class>::value) {
|
||||
#else
|
||||
@@ -1725,7 +1709,7 @@ void fill_crossdata_for_intersect(const FatCo<T> &curco,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case isect_result<vec2<T>>::LINE_LINE_EXACT: {
|
||||
case isect_result<VecBase<T, 2>>::LINE_LINE_EXACT: {
|
||||
if (lambda == 0) {
|
||||
fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
|
||||
}
|
||||
@@ -1740,7 +1724,7 @@ void fill_crossdata_for_intersect(const FatCo<T> &curco,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case isect_result<vec2<T>>::LINE_LINE_NONE: {
|
||||
case isect_result<VecBase<T, 2>>::LINE_LINE_NONE: {
|
||||
#ifdef WITH_GMP
|
||||
if (std::is_same<T, mpq_class>::value) {
|
||||
BLI_assert(false);
|
||||
@@ -1756,7 +1740,7 @@ void fill_crossdata_for_intersect(const FatCo<T> &curco,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case isect_result<vec2<T>>::LINE_LINE_COLINEAR: {
|
||||
case isect_result<VecBase<T, 2>>::LINE_LINE_COLINEAR: {
|
||||
if (distance_squared(va->co.approx, v2->co.approx) <=
|
||||
distance_squared(vb->co.approx, v2->co.approx))
|
||||
{
|
||||
@@ -1836,7 +1820,7 @@ void get_next_crossing_from_edge(CrossData<T> *cd,
|
||||
{
|
||||
CDTVert<T> *va = cd->in->vert;
|
||||
CDTVert<T> *vb = cd->in->next->vert;
|
||||
vec2<T> curco = interpolate(va->co.exact, vb->co.exact, cd->lambda);
|
||||
VecBase<T, 2> curco = interpolate(va->co.exact, vb->co.exact, cd->lambda);
|
||||
FatCo<T> fat_curco(curco);
|
||||
SymEdge<T> *se_ac = sym(cd->in)->next;
|
||||
CDTVert<T> *vc = se_ac->next->vert;
|
||||
@@ -2376,8 +2360,8 @@ template<typename T> void remove_non_constraint_edges_leave_valid_bmesh(CDT_stat
|
||||
if (!is_deleted_edge(e) && !is_constrained_edge(e)) {
|
||||
dissolvable_edges.append(EdgeToSort<T>());
|
||||
dissolvable_edges[i].e = e;
|
||||
const vec2<double> &co1 = e->symedges[0].vert->co.approx;
|
||||
const vec2<double> &co2 = e->symedges[1].vert->co.approx;
|
||||
const double2 &co1 = e->symedges[0].vert->co.approx;
|
||||
const double2 &co2 = e->symedges[1].vert->co.approx;
|
||||
dissolvable_edges[i].len_squared = distance_squared(co1, co2);
|
||||
i++;
|
||||
}
|
||||
@@ -2544,7 +2528,7 @@ template<typename T> void detect_holes(CDT_state<T> *cdt_state)
|
||||
/* Pick a ray end almost certain to be outside everything and in direction
|
||||
* that is unlikely to hit a vertex or overlap an edge exactly. */
|
||||
FatCo<T> ray_end;
|
||||
ray_end.exact = vec2<T>(123456, 654321);
|
||||
ray_end.exact = VecBase<T, 2>(123456, 654321);
|
||||
for (int i : region_rep_face.index_range()) {
|
||||
CDTFace<T> *f = region_rep_face[i];
|
||||
FatCo<T> mid;
|
||||
@@ -2568,13 +2552,13 @@ template<typename T> void detect_holes(CDT_state<T> *cdt_state)
|
||||
e->symedges[0].vert->co.exact,
|
||||
e->symedges[1].vert->co.exact);
|
||||
switch (isect.kind) {
|
||||
case isect_result<vec2<T>>::LINE_LINE_CROSS: {
|
||||
case isect_result<VecBase<T, 2>>::LINE_LINE_CROSS: {
|
||||
hits++;
|
||||
break;
|
||||
}
|
||||
case isect_result<vec2<T>>::LINE_LINE_EXACT:
|
||||
case isect_result<vec2<T>>::LINE_LINE_NONE:
|
||||
case isect_result<vec2<T>>::LINE_LINE_COLINEAR:
|
||||
case isect_result<VecBase<T, 2>>::LINE_LINE_EXACT:
|
||||
case isect_result<VecBase<T, 2>>::LINE_LINE_NONE:
|
||||
case isect_result<VecBase<T, 2>>::LINE_LINE_COLINEAR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2692,7 +2676,7 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
|
||||
}
|
||||
}
|
||||
}
|
||||
result.vert = Array<vec2<T>>(nv);
|
||||
result.vert = Array<VecBase<T, 2>>(nv);
|
||||
if (cdt_state->need_ids) {
|
||||
result.vert_orig = Array<Vector<int>>(nv);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ template<typename T> CDT_input<T> fill_input_from_string(const char *spec)
|
||||
if (nverts == 0) {
|
||||
return CDT_input<T>();
|
||||
}
|
||||
Array<vec2<T>> verts(nverts);
|
||||
Array<VecBase<T, 2>> verts(nverts);
|
||||
Array<std::pair<int, int>> edges(nedges);
|
||||
Array<Vector<int>> faces(nfaces);
|
||||
int i = 0;
|
||||
@@ -55,7 +55,7 @@ template<typename T> CDT_input<T> fill_input_from_string(const char *spec)
|
||||
iss >> dp0 >> dp1;
|
||||
T p0(dp0);
|
||||
T p1(dp1);
|
||||
verts[i] = vec2<T>(p0, p1);
|
||||
verts[i] = VecBase<T, 2>(p0, p1);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
@@ -264,7 +264,7 @@ static bool draw_append = false; /* Will be set to true after first call. */
|
||||
|
||||
template<typename T>
|
||||
void graph_draw(const std::string &label,
|
||||
const Array<vec2<T>> &verts,
|
||||
const Array<VecBase<T, 2>> &verts,
|
||||
const Array<std::pair<int, int>> &edges,
|
||||
const Array<Vector<int>> &faces)
|
||||
{
|
||||
@@ -286,9 +286,9 @@ void graph_draw(const std::string &label,
|
||||
if (verts.is_empty()) {
|
||||
return;
|
||||
}
|
||||
vec2<double> vmin(1e10, 1e10);
|
||||
vec2<double> vmax(-1e10, -1e10);
|
||||
for (const vec2<T> &v : verts) {
|
||||
double2 vmin(1e10, 1e10);
|
||||
double2 vmax(-1e10, -1e10);
|
||||
for (const VecBase<T, 2> &v : verts) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
double dvi = math_to_double(v[i]);
|
||||
if (dvi < vmin[i]) {
|
||||
@@ -341,15 +341,15 @@ void graph_draw(const std::string &label,
|
||||
for (const Vector<int> &fverts : faces) {
|
||||
f << "<polygon fill=\"azure\" stroke=\"none\"\n points=\"";
|
||||
for (int vi : fverts) {
|
||||
const vec2<T> &co = verts[vi];
|
||||
const VecBase<T, 2> &co = verts[vi];
|
||||
f << SX(co[0]) << "," << SY(co[1]) << " ";
|
||||
}
|
||||
f << "\"\n />\n";
|
||||
}
|
||||
|
||||
for (const std::pair<int, int> &e : edges) {
|
||||
const vec2<T> &uco = verts[e.first];
|
||||
const vec2<T> &vco = verts[e.second];
|
||||
const VecBase<T, 2> &uco = verts[e.first];
|
||||
const VecBase<T, 2> &vco = verts[e.second];
|
||||
int strokew = thin_line;
|
||||
f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\""
|
||||
<< SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\""
|
||||
@@ -364,7 +364,7 @@ void graph_draw(const std::string &label,
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (const vec2<T> &vco : verts) {
|
||||
for (const VecBase<T, 2> &vco : verts) {
|
||||
f << R"(<circle fill="black" cx=")" << SX(vco[0]) << "\" cy=\"" << SY(vco[1]) << "\" r=\""
|
||||
<< vert_radius << "\">\n";
|
||||
f << " <title>[" << i << "]" << vco << "</title>\n";
|
||||
@@ -384,18 +384,18 @@ void graph_draw(const std::string &label,
|
||||
/* Should tests draw their output to an html file? */
|
||||
constexpr bool DO_DRAW = false;
|
||||
|
||||
template<typename T> void expect_coord_near(const vec2<T> &testco, const vec2<T> &refco);
|
||||
template<typename T>
|
||||
void expect_coord_near(const VecBase<T, 2> &testco, const VecBase<T, 2> &refco);
|
||||
|
||||
#ifdef WITH_GMP
|
||||
template<>
|
||||
void expect_coord_near<mpq_class>(const vec2<mpq_class> &testco, const vec2<mpq_class> &refco)
|
||||
template<> void expect_coord_near<mpq_class>(const mpq2 &testco, const mpq2 &refco)
|
||||
{
|
||||
EXPECT_EQ(testco[0], refco[0]);
|
||||
EXPECT_EQ(testco[0], refco[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<> void expect_coord_near<double>(const vec2<double> &testco, const vec2<double> &refco)
|
||||
template<> void expect_coord_near<double>(const double2 &testco, const double2 &refco)
|
||||
{
|
||||
EXPECT_NEAR(testco[0], refco[0], 1e-5);
|
||||
EXPECT_NEAR(testco[1], refco[1], 1e-5);
|
||||
@@ -428,7 +428,7 @@ template<typename T> void onept_test()
|
||||
EXPECT_EQ(out.edge.size(), 0);
|
||||
EXPECT_EQ(out.face.size(), 0);
|
||||
if (out.vert.size() >= 1) {
|
||||
expect_coord_near<T>(out.vert[0], vec2<T>(0, 0));
|
||||
expect_coord_near<T>(out.vert[0], VecBase<T, 2>(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,8 +450,8 @@ template<typename T> void twopt_test()
|
||||
EXPECT_NE(v1_out, -1);
|
||||
EXPECT_NE(v0_out, v1_out);
|
||||
if (out.vert.size() >= 1) {
|
||||
expect_coord_near<T>(out.vert[v0_out], vec2<T>(0.0, -0.75));
|
||||
expect_coord_near<T>(out.vert[v1_out], vec2<T>(0.0, 0.75));
|
||||
expect_coord_near<T>(out.vert[v0_out], VecBase<T, 2>(0.0, -0.75));
|
||||
expect_coord_near<T>(out.vert[v1_out], VecBase<T, 2>(0.0, 0.75));
|
||||
}
|
||||
int e0_out = get_output_edge_index(out, v0_out, v1_out);
|
||||
EXPECT_EQ(e0_out, 0);
|
||||
@@ -787,7 +787,7 @@ template<typename T> void crosssegs_test()
|
||||
}
|
||||
EXPECT_NE(v_intersect, -1);
|
||||
if (v_intersect != -1) {
|
||||
expect_coord_near<T>(out.vert[v_intersect], vec2<T>(0, 0));
|
||||
expect_coord_near<T>(out.vert[v_intersect], VecBase<T, 2>(0, 0));
|
||||
}
|
||||
}
|
||||
if (DO_DRAW) {
|
||||
@@ -1156,8 +1156,8 @@ template<typename T> void overlapfaces_test()
|
||||
v_int1 = 13;
|
||||
v_int2 = 12;
|
||||
}
|
||||
expect_coord_near<T>(out.vert[v_int1], vec2<T>(1, 0.5));
|
||||
expect_coord_near<T>(out.vert[v_int2], vec2<T>(0.5, 1));
|
||||
expect_coord_near<T>(out.vert[v_int1], VecBase<T, 2>(1, 0.5));
|
||||
expect_coord_near<T>(out.vert[v_int2], VecBase<T, 2>(0.5, 1));
|
||||
EXPECT_EQ(out.vert_orig[v_int1].size(), 0);
|
||||
EXPECT_EQ(out.vert_orig[v_int2].size(), 0);
|
||||
int f0_out = get_output_tri_index(out, v_out[1], v_int1, v_out[4]);
|
||||
@@ -1785,7 +1785,7 @@ void text_test(
|
||||
constexpr int narcs = 4;
|
||||
int b_npts = b_before_arcs_in.vert.size() + narcs * arc_points_num;
|
||||
constexpr int b_nfaces = 3;
|
||||
Array<vec2<T>> b_vert(b_npts);
|
||||
Array<VecBase<T, 2>> b_vert(b_npts);
|
||||
Array<Vector<int>> b_face(b_nfaces);
|
||||
std::copy(b_before_arcs_in.vert.begin(), b_before_arcs_in.vert.end(), b_vert.begin());
|
||||
std::copy(b_before_arcs_in.face.begin(), b_before_arcs_in.face.end(), b_face.begin());
|
||||
@@ -1819,16 +1819,16 @@ void text_test(
|
||||
default:
|
||||
BLI_assert(false);
|
||||
}
|
||||
vec2<T> start_co = b_vert[arc_origin_vert];
|
||||
vec2<T> end_co = b_vert[arc_terminal_vert];
|
||||
vec2<T> center_co = 0.5 * (start_co + end_co);
|
||||
VecBase<T, 2> start_co = b_vert[arc_origin_vert];
|
||||
VecBase<T, 2> end_co = b_vert[arc_terminal_vert];
|
||||
VecBase<T, 2> center_co = 0.5 * (start_co + end_co);
|
||||
BLI_assert(start_co[0] == end_co[0]);
|
||||
double radius = abs(math_to_double<T>(end_co[1] - center_co[1]));
|
||||
double angle_delta = M_PI / (arc_points_num + 1);
|
||||
int start_vert = b_before_arcs_in.vert.size() + arc * arc_points_num;
|
||||
Vector<int> &face = b_face[(arc <= 1) ? 0 : arc - 1];
|
||||
for (int i = 0; i < arc_points_num; ++i) {
|
||||
vec2<T> delta;
|
||||
VecBase<T, 2> delta;
|
||||
float ang = ccw ? (-M_PI_2 + (i + 1) * angle_delta) : (M_PI_2 - (i + 1) * angle_delta);
|
||||
delta[0] = T(radius * cos(ang));
|
||||
delta[1] = T(radius * sin(ang));
|
||||
@@ -1848,7 +1848,7 @@ void text_test(
|
||||
in.face = b_face;
|
||||
}
|
||||
else {
|
||||
in.vert = Array<vec2<T>>(tot_instances * b_vert.size());
|
||||
in.vert = Array<VecBase<T, 2>>(tot_instances * b_vert.size());
|
||||
in.face = Array<Vector<int>>(tot_instances * b_face.size());
|
||||
T cur_x = T(0);
|
||||
T cur_y = T(0);
|
||||
@@ -1857,7 +1857,7 @@ void text_test(
|
||||
int instance = 0;
|
||||
for (int line = 0; line < lines_num; ++line) {
|
||||
for (int let = 0; let < lets_per_line_num; ++let) {
|
||||
vec2<T> co_offset(cur_x, cur_y);
|
||||
VecBase<T, 2> co_offset(cur_x, cur_y);
|
||||
int in_v_offset = instance * b_vert.size();
|
||||
for (int v = 0; v < b_vert.size(); ++v) {
|
||||
in.vert[in_v_offset + v] = b_vert[v] + co_offset;
|
||||
@@ -2102,7 +2102,7 @@ void rand_delaunay_test(int test_kind,
|
||||
}
|
||||
|
||||
CDT_input<T> in;
|
||||
in.vert = Array<vec2<T>>(npts);
|
||||
in.vert = Array<VecBase<T, 2>>(npts);
|
||||
if (nedges > 0) {
|
||||
in.edge = Array<std::pair<int, int>>(nedges);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user