Get basic matching algorithm working

This commit is contained in:
Shaunak Kishore
2015-09-07 17:13:13 -04:00
parent fef113a3a6
commit c722fae666
2 changed files with 57 additions and 11 deletions

View File

@ -1,3 +1,4 @@
var MAX_BRIDGE_DISTANCE = 64;
var MIN_CORNER_ANGLE = 0.1*Math.PI;
var MIN_CORNER_TANGENT_DISTANCE = 4;
@ -21,6 +22,9 @@ var Angle = {
}
return result;
},
penalty: function(diff) {
return diff*diff*(diff < 0 ? 4 : 1);
},
};
// Helper methods for use with "points", which are just pairs of integers.
@ -138,19 +142,45 @@ function get_2x_area(path) {
// Returns a list of critical segments that are arrayed around the corner.
// Each of these segments will include a d value, an "in" bit, and an "out" bit.
function get_segments(corners) {
var map = {};
var result = [[], []];
for (var i = 0; i < corners.length; i++) {
var corner = corners[i];
for (var j = 0; j < 2; j++) {
var key = Point.key(corner.indices[j]);
if (!map.hasOwnProperty(key)) {
map[key] = {segment: corner.segments[j]};
}
result[j].push({
angle: corners[i].angles[j],
point: corners[i].point,
});
}
map[Point.key(corner.indices[0])].in = true;
map[Point.key(corner.indices[1])].out = true;
}
return _.values(map);
return result;
}
// Takes a list of segments and returns a bipartite match array between them.
// If array[i] === j, then segments[0][i] is matched with segments[1][j].
function match_segments(segments) {
var matrix = [];
for (var i = 0; i < segments[0].length; i++) {
matrix.push([]);
for (var j = 0; j < segments[0].length; j++) {
matrix[i].push(score_segments(segments[0][i], segments[1][j]));
}
}
return (new Hungarian(matrix)).x_match;
}
// Takes two segments and returns the score that should be assigned to matching
// the in segment to the out segment. The score will generally be negative.
function score_segments(ins, out) {
var diff = Point.subtract(out.point, ins.point);
if (Point.equal(diff, [0, 0])) {
return -Angle.penalty(Angle.subtract(out.angle, ins.angle));
}
var angle = Math.atan2(diff[1], diff[0]);
var threshold = Math.pow(MAX_BRIDGE_DISTANCE, 2);
var score = 0;
score -= Angle.penalty(Angle.subtract(angle, ins.angle));
score -= Angle.penalty(Angle.subtract(out.angle, angle));
score -= Point.distance2(out.point, ins.point)/threshold;
return score;
}
function Endpoint(paths, index) {
@ -192,9 +222,12 @@ this.get_glyph_render_data = function(glyph) {
}
}
var corners = endpoints.filter(function(x) { return x.corner; });
var segments = get_segments(corners);
var matching = match_segments(segments);
return {
d: Glyphs.get_svg_path(glyph),
endpoints: endpoints,
segments: get_segments(corners),
segments: segments,
matching: matching,
};
}