mirror of
https://github.com/skishore/makemeahanzi.git
synced 2025-10-29 09:57:38 +08:00
Get bridges working
This commit is contained in:
@ -53,7 +53,7 @@ Tracker.autorun(() => {
|
|||||||
const glyph = Session.get('editor.glyph');
|
const glyph = Session.get('editor.glyph');
|
||||||
if (!glyph) return;
|
if (!glyph) return;
|
||||||
if (!last_glyph || glyph.character !== last_glyph.character) {
|
if (!last_glyph || glyph.character !== last_glyph.character) {
|
||||||
stage = new stages.strokes(glyph);
|
stage = new stages.bridges(glyph);
|
||||||
}
|
}
|
||||||
stage.refresh(glyph);
|
stage.refresh(glyph);
|
||||||
last_glyph = glyph;
|
last_glyph = glyph;
|
||||||
|
|||||||
95
client/lib/bridges.js
Normal file
95
client/lib/bridges.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const bridgeKey = (bridge) => bridge.map(Point.key).join('-');
|
||||||
|
|
||||||
|
const removeBridge = (bridges, bridge) => {
|
||||||
|
const keys = {};
|
||||||
|
keys[bridgeKey(bridge)] = true;
|
||||||
|
keys[bridgeKey(bridge.reverse())] = true;
|
||||||
|
return bridges.filter((bridge) => !keys[bridgeKey(bridge)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
stages.bridges = class BridgesStage extends stages.AbstractStage {
|
||||||
|
constructor(glyph) {
|
||||||
|
super();
|
||||||
|
Session.set('stage.type', 'bridges');
|
||||||
|
Session.set('stage.instructions',
|
||||||
|
'Connect each pair of points on the glyph outline such that ' +
|
||||||
|
'the segment connecting those points is part of some stroke ' +
|
||||||
|
'outline. Click on a bridge to drop it.');
|
||||||
|
const bridges = stroke_extractor.getBridges(glyph);
|
||||||
|
this.bridges = bridges.bridges;
|
||||||
|
this.endpoints = [];
|
||||||
|
bridges.endpoints.map(
|
||||||
|
(path) => this.endpoints = this.endpoints.concat(path));
|
||||||
|
this.selected_point = undefined;
|
||||||
|
glyph.stages.strokes = glyph.stages.strokes || this.bridges;
|
||||||
|
}
|
||||||
|
handleClickOnBridge(glyph, bridge) {
|
||||||
|
glyph.stages.bridges = removeBridge(glyph.stages.bridges, bridge);
|
||||||
|
Session.set('editor.glyph', glyph);
|
||||||
|
}
|
||||||
|
handleClickOnPoint(glyph, point) {
|
||||||
|
if (this.selected_point === undefined) {
|
||||||
|
this.selected_point = point;
|
||||||
|
this.refresh(glyph);
|
||||||
|
return;
|
||||||
|
} else if (Point.equal(point, this.selected_point)) {
|
||||||
|
this.selected_point = undefined;
|
||||||
|
this.refresh(glyph);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bridge = [point, this.selected_point];
|
||||||
|
this.selected_point = undefined;
|
||||||
|
const without = removeBridge(glyph.stages.bridges, bridge);
|
||||||
|
if (without.length < glyph.stages.bridges.length) {
|
||||||
|
this.refresh(glyph);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glyph.stages.bridges.push(bridge);
|
||||||
|
Session.set('editor.glyph', glyph);
|
||||||
|
}
|
||||||
|
handleEvent(glyph, event, template) {
|
||||||
|
if (template.x1 !== undefined) {
|
||||||
|
this.handleClickOnBridge(
|
||||||
|
glyph, [[template.x1, template.y1], [template.x2, template.y2]]);
|
||||||
|
} else if (template.cx !== undefined) {
|
||||||
|
this.handleClickOnPoint(glyph, [template.cx, template.cy]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refresh(glyph) {
|
||||||
|
Session.set('stage.paths',
|
||||||
|
[{d: glyph.stages.path, fill: 'gray', stroke: 'gray'}]);
|
||||||
|
const keys = {};
|
||||||
|
this.bridges.map((bridge) => {
|
||||||
|
keys[bridgeKey(bridge)] = true;
|
||||||
|
keys[bridgeKey(bridge.reverse())] = true;
|
||||||
|
});
|
||||||
|
Session.set('stage.lines', glyph.stages.bridges.map((bridge) => ({
|
||||||
|
cls: 'selectable',
|
||||||
|
stroke: keys[bridgeKey(bridge)] ? 'red' : 'purple',
|
||||||
|
x1: bridge[0][0],
|
||||||
|
y1: bridge[0][1],
|
||||||
|
x2: bridge[1][0],
|
||||||
|
y2: bridge[1][1],
|
||||||
|
})));
|
||||||
|
Session.set('stage.points', this.endpoints.map((endpoint) => {
|
||||||
|
let color = endpoint.corner ? 'red' : 'black';
|
||||||
|
if (this.selected_point &&
|
||||||
|
Point.equal(endpoint.point, this.selected_point)) {
|
||||||
|
color = 'purple';
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
cls: 'selectable',
|
||||||
|
cx: endpoint.point[0],
|
||||||
|
cy: endpoint.point[1],
|
||||||
|
fill: color,
|
||||||
|
stroke: color,
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
const strokes = stroke_extractor.getStrokes(glyph);
|
||||||
|
const n = strokes.strokes.length;
|
||||||
|
const message = `Extracted ${n} stroke${n == 1 ? '' : 's'}.`;
|
||||||
|
Session.set('stage.status', strokes.log.concat([{message: message}]));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -86,7 +86,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
path.selectable:hover {
|
path.selectable:hover, line.selectable:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
stroke: blue;
|
stroke: blue;
|
||||||
stroke-width: 8;
|
stroke-width: 8;
|
||||||
|
|||||||
@ -363,7 +363,8 @@ this.stroke_extractor.getBridges = (glyph, classifier) => {
|
|||||||
endpoints.push(new Endpoint(paths, [i, j]));
|
endpoints.push(new Endpoint(paths, [i, j]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return getBridges(endpoints, classifier || handTunedClassifier);
|
const bridges = getBridges(endpoints, classifier || handTunedClassifier);
|
||||||
|
return {endpoints: endpoints, bridges: bridges};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stroke_extractor.getStrokes = (glyph) => {
|
this.stroke_extractor.getStrokes = (glyph) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user