jsketcher/web/app/sketcher/tools/loop-pick.js
2022-08-15 23:47:20 -07:00

145 lines
3.1 KiB
JavaScript

import {Tool} from './tool'
import {Graph} from '../../utils/graph'
import {Styles} from '../styles'
import {DEFAULT_SEARCH_BUFFER} from "../viewer2d";
export class LoopPickTool extends Tool {
constructor(name, viewer) {
super(name, viewer);
this.loops = new Map();
this.marked = new Set();
this.pickedLoop = null;
this.pointToObject = new Map();
}
restart() {
this.sendHint('pick a polygon');
this.reindexLoops();
this.marked.clear();
this.pointToObject.clear();
this.pickedLoop = null;
}
cleanup() {
this.clearMarked();
}
clearMarked() {
this.viewer.withdrawAll('tool');
}
mark(obj) {
this.viewer.capture('tool', obj);
}
otherEnd(point) {
if (point.parent.a.id === point.id) {
return point.parent.b;
} else {
return point.parent.a;
}
}
reindexLoops() {
this.loops.clear();
const points = [];
this.viewer.accept((obj) => {
if (obj.TYPE === 'Point' && obj.parent &&
obj.parent.a && obj.parent.b && (obj.parent.a === obj || obj.parent.b === obj)) {
points.push(obj);
}
return true;
});
const graph = {
connections : (p) => {
const conns = []
p.visitLinked(l => conns.push(l));
conns.push(this.otherEnd(p));
return conns;
},
at : function(index) {
return points[index];
},
size : function() {
return points.length;
}
};
const loopPoints = Graph.findAllLoops(graph, (p) => p.id, (a, b) => a.id === b.id);
const loops = loopPoints.map(l => this.cleanLoop(l));
for (const loop of loops) {
for (const point of loop.points) {
this.loops.set(point, loop);
}
}
}
cleanLoop(loop) {
const points = [];
const edges = [];
for (let i = 0; i < loop.length; i++) {
const a = loop[i];
const b = loop[(i + 1) % loop.length];
if (a.parent == b.parent) {
points.push(a);
edges.push(b.parent);
}
}
return {points, edges};
}
mousemove(e) {
this.clearMarked();
this.pickedLoop = null;
const p = this.viewer.screenToModel(e);
this.pickedLoop = this.pickLoop(p);
if (this.pickedLoop != null) {
for (const obj of this.pickedLoop.edges) {
this.mark(obj);
}
}
this.viewer.refresh();
}
pickLoop(p) {
const pickResult = this.viewer.search(p.x, p.y, DEFAULT_SEARCH_BUFFER, true, false, []);
for (const obj of pickResult) {
for (const point of [obj.a, obj.b]) {
const loop = this.loops.get(point);
if (loop) {
return loop;
}
}
}
return null;
}
mousedown(e) {
if (this.pickedLoop == null) {
this.viewer.toolManager.releaseControl();
this.viewer.toolManager.tool.mousedown(e);
} else {
this.onMousedown(e);
}
}
onMousedown(e) {}
}
function getEdgeFor(a, b) {
if (isEdgeFor(a.parent, a, b)) {
return a.parent
} else if (isEdgeFor(b.parent, a, b)) {
return b.parent;
} else {
return null;
}
}
function isEdgeFor(obj, a, b) {
return (obj.a.id == a.id && obj.b.id == b.id) || (obj.a.id == b.id && obj.b.id == b.id)
}