Relative neighbourhood graph with aligned tangents and smoothly interpolated connections using bezier interpolation.
Relative Neighbourhood Graph (RNG)
// PRIMITIVE WRANGLE
int pts[] = primpoints(0, i@primnum);
vector pos_0 = point(0, 'P', pts[0]);
vector pos_1 = point(0, 'P', pts[1]);
float radius = distance(pos_0, pos_1) + 1e-5;
int pts_0[] = nearpoints(0, pos_0, radius);
int pts_1[] = nearpoints(0, pos_1, radius);
int match = 0;
foreach(int pt; pts_0){
int index = find(pts_1, pt);
match += index >= 0;
if(match >= 3){
removeprim(0, i@primnum, 0);
break;
}
}
Tangents
// VERTEX WRANGLE
vector pos = prim(0, 'P', i@primnum);
vector dir = normalize(pos - v@P);
v@tangent = dir;
Tangent Alignment
// VERTEX WRANGLE
int verts[] = pointvertices(0, i@ptnum);
removevalue(verts, i@vtxnum);
float align_best = 1.0;
vector tangent_best = 0;
foreach (int vtx; verts) {
vector tangent_vtx = normalize(vertex(0, "tangent", vtx));
float align = dot(v@tangent, tangent_vtx);
if (align < align_best) {
align_best = align;
tangent_best = tangent_vtx;
}
}
vector axis = normalize(v@tangent - tangent_best);
v@tangent = axis;
Spline Interpolation
// POINT WRANGLE
float perim = primintrinsic(0, 'measuredperimeter', i@primnum);
vector pos_0 = primuv(0, 'P', i@primnum, {0,0,0});
vector pos_n = primuv(0, 'P', i@primnum, {1,0,0});
vector tangent_0 = primuv(0, 'tangent', i@primnum, {0,0,0});
vector tangent_n = primuv(0, 'tangent', i@primnum, {1,0,0});
vector pos_1 = pos_0 + tangent_0 * perim * 0.25;
vector pos_2 = pos_n + tangent_n * perim * 0.25;
vector pos[] = array(pos_0, pos_1, pos_2, pos_n);
float u = vertexcurveparam(0, i@vtxnum);
vector pos_curve = spline('bezier', u, pos);
v@P = pos_curve;