mirror of
				https://github.com/skishore/makemeahanzi.git
				synced 2025-10-31 02:45:49 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			87 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "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('bridges');
 | |
|     const bridges = stroke_extractor.getBridges(glyph.stages.path);
 | |
|     this.original = bridges.bridges;
 | |
|     this.adjusted = glyph.stages.bridges || this.original;
 | |
|     this.endpoints = bridges.endpoints.reduce((x, y) => x.concat(y), []);
 | |
|     this.path = glyph.stages.path;
 | |
|     this.selected_point = undefined;
 | |
|   }
 | |
|   handleClickOnBridge(bridge) {
 | |
|     this.adjusted = removeBridge(this.adjusted, bridge);
 | |
|   }
 | |
|   handleClickOnPoint(point) {
 | |
|     if (this.selected_point === undefined) {
 | |
|       this.selected_point = point;
 | |
|       this.refreshUI();
 | |
|       return;
 | |
|     } else if (Point.equal(point, this.selected_point)) {
 | |
|       this.selected_point = undefined;
 | |
|       this.refreshUI();
 | |
|       return;
 | |
|     }
 | |
|     const bridge = [point, this.selected_point];
 | |
|     this.selected_point = undefined;
 | |
|     const without = removeBridge(this.adjusted, bridge);
 | |
|     if (without.length < this.adjusted.length) {
 | |
|       this.refreshUI();
 | |
|       return;
 | |
|     }
 | |
|     this.adjusted.push(bridge);
 | |
|   }
 | |
|   handleEvent(event, template) {
 | |
|     if (template.x1 !== undefined) {
 | |
|       const bridge = [[template.x1, template.y1], [template.x2, template.y2]];
 | |
|       this.handleClickOnBridge(bridge);
 | |
|     } else if (template.cx !== undefined) {
 | |
|       this.handleClickOnPoint([template.cx, template.cy]);
 | |
|     }
 | |
|   }
 | |
|   refreshUI() {
 | |
|     Session.set('stage.paths', [{d: this.path, fill: 'gray', stroke: 'gray'}]);
 | |
|     const keys = {};
 | |
|     this.original.map((bridge) => {
 | |
|       keys[bridgeKey(bridge)] = true;
 | |
|       keys[bridgeKey(bridge.reverse())] = true;
 | |
|     });
 | |
|     Session.set('stage.lines', this.adjusted.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(this.path, this.adjusted);
 | |
|     const n = strokes.strokes.length;
 | |
|     const message = `Extracted ${n} stroke${n == 1 ? '' : 's'}.`;
 | |
|     Session.set('stage.status', strokes.log.concat([{message: message}]));
 | |
|   }
 | |
| }
 | 
