mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
264 lines
6.9 KiB
JavaScript
264 lines
6.9 KiB
JavaScript
import {
|
|
AngleBetweenDimension,
|
|
DiameterDimension,
|
|
findCenter,
|
|
HDimension, LinearDimension,
|
|
VDimension,
|
|
} from '../shapes/dim'
|
|
import Vector from 'math/vector';
|
|
import {EndPoint} from '../shapes/point'
|
|
import {Tool} from './tool'
|
|
import {DragTool} from "./drag";
|
|
import {isInstanceOf} from "../actions/matchUtils";
|
|
import {Segment} from "../shapes/segment";
|
|
import {DEFAULT_SEARCH_BUFFER} from "../viewer2d";
|
|
import {distance} from "../../../../modules/math/commons";
|
|
import {_negate, cross2d} from "math/vec";
|
|
|
|
export class AddDimTool extends Tool {
|
|
|
|
constructor(name, viewer, layer, dimCreation) {
|
|
super(name, viewer);
|
|
this.layer = layer;
|
|
this.dim = null;
|
|
this._v = new Vector(0, 0, 0);
|
|
this.dimCreation = dimCreation;
|
|
}
|
|
|
|
mousemove(e) {
|
|
var p = this.viewer.screenToModel(e);
|
|
this.viewer.snap(p.x, p.y, []);
|
|
if (this.dim != null) {
|
|
this.dim.b.x = p.x;
|
|
this.dim.b.y = p.y;
|
|
}
|
|
this.viewer.refresh();
|
|
}
|
|
|
|
mouseup(e) {
|
|
|
|
if (this.viewer.snapped == null) {
|
|
if (this.dim === null) {
|
|
const result = this.viewer.pick(e);
|
|
if (result.length >= 0) {
|
|
const segment = result.find(e => isInstanceOf(e, Segment));
|
|
if (segment) {
|
|
this.dim = this.dimCreation(segment.a, segment.b);
|
|
this.dim.offset = 0;
|
|
this.layer.add(this.dim);
|
|
this.viewer.toolManager.switchTool(new DragTool(this.dim, this.viewer));
|
|
this.viewer.toolManager.tool.mousedown(e);
|
|
this.viewer.refresh();
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
const p = this.viewer.snapped;
|
|
this.viewer.cleanSnap();
|
|
|
|
if (this.dim == null) {
|
|
this.viewer.historyManager.checkpoint();
|
|
this.dim = this.dimCreation(p, new EndPoint(p.x, p.y));
|
|
this.dim.offset = 0;
|
|
this.layer.add(this.dim);
|
|
this.viewer.refresh();
|
|
} else {
|
|
this.dim.b = p;
|
|
this.viewer.toolManager.switchTool(new DragTool(this.dim, this.viewer));
|
|
this.viewer.toolManager.tool.mousedown(e);
|
|
this.viewer.refresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
export class AddFreeDimTool extends AddDimTool {
|
|
constructor(viewer, layer) {
|
|
super('free dimension', viewer, layer, (a, b) => new LinearDimension(a, b));
|
|
}
|
|
}
|
|
|
|
export class AddHorizontalDimTool extends AddDimTool {
|
|
constructor(viewer, layer) {
|
|
super('horizontal dimension', viewer, layer, (a, b) => new HDimension(a, b));
|
|
}
|
|
}
|
|
|
|
export class AddVerticalDimTool extends AddDimTool {
|
|
constructor(viewer, layer) {
|
|
super('vertical dimension', viewer, layer, (a, b) => new VDimension(a, b));
|
|
}
|
|
}
|
|
|
|
export class AddCircleDimTool extends Tool {
|
|
constructor(viewer, layer) {
|
|
super('arc/circle dimension', viewer);
|
|
this.layer = layer;
|
|
this.dim = new DiameterDimension(null);
|
|
this.viewer.add(this.dim, this.layer);
|
|
}
|
|
|
|
mousemove(e) {
|
|
var p = this.viewer.screenToModel(e);
|
|
var objects = this.viewer.search(p.x, p.y, DEFAULT_SEARCH_BUFFER, true, false, []).filter(function (o) {
|
|
return o.TYPE === 'Circle' || o.TYPE === 'Arc';
|
|
});
|
|
|
|
if (objects.length !== 0) {
|
|
this.dim.obj = objects[0];
|
|
this.viewer.capture('tool', [this.dim.obj], true);
|
|
} else {
|
|
this.dim.obj = null;
|
|
this.viewer.withdrawAll('tool');
|
|
}
|
|
if (this.dim.obj !== null) {
|
|
this.dim.angle = Math.atan2(p.y - this.dim.obj.c.y, p.x - this.dim.obj.c.x);
|
|
}
|
|
this.viewer.refresh();
|
|
}
|
|
|
|
mouseup(e) {
|
|
if (this.dim.obj !== null) {
|
|
this.viewer.historyManager.checkpoint();
|
|
} else {
|
|
this.viewer.remove(this.dim);
|
|
}
|
|
this.viewer.withdrawAll('tool');
|
|
this.viewer.refresh();
|
|
this.viewer.toolManager.releaseControl();
|
|
}
|
|
}
|
|
|
|
export class AddAngleTool extends Tool {
|
|
|
|
constructor(name, viewer, layer, dimCreation) {
|
|
super(name, viewer);
|
|
this.layer = layer;
|
|
this.a = null;
|
|
this.dim = null;
|
|
this.dimCreation = dimCreation;
|
|
}
|
|
|
|
mousemove(e) {
|
|
const p = this.viewer.screenToModel(e);
|
|
|
|
const result = this.viewer.search(p.x, p.y, DEFAULT_SEARCH_BUFFER, true, false, []).filter(o => o.TYPE === 'Segment');
|
|
const [segment] = result;
|
|
|
|
if (this.dim) {
|
|
let center;
|
|
if (!this.dim.isAnnotation) {
|
|
let configuration;
|
|
[center, configuration] = this.classify(p.x, p.y);
|
|
if (configuration) {
|
|
this.dim.configuration = configuration;
|
|
}
|
|
} else {
|
|
const line1 = this.dim.a, line2 = this.dim.b;
|
|
const v1 = [line1.ny, - line1.nx];
|
|
const v2 = [line2.ny, - line2.nx];
|
|
center = findCenter(line1.a, line1.b, line2.a, line2.b, v1[0], v1[1], v2[0], v2[1]);
|
|
}
|
|
if (!center) {
|
|
center = segment.a;
|
|
}
|
|
let [cx, cy] = center;
|
|
this.dim.offset = distance(cx, cy, p.x, p.y);
|
|
|
|
} else {
|
|
if (segment) {
|
|
this.viewer.capture('tool', [segment], true);
|
|
} else {
|
|
this.viewer.withdrawAll('tool');
|
|
}
|
|
}
|
|
|
|
|
|
this.viewer.refresh();
|
|
}
|
|
|
|
mouseup(e) {
|
|
|
|
const p = this.viewer.screenToModel(e);
|
|
|
|
const [segment] = this.viewer.captured.tool;
|
|
this.viewer.withdrawAll('tool');
|
|
|
|
if (this.a === null) {
|
|
if (!segment) {
|
|
this.viewer.toolManager.releaseControl();
|
|
this.viewer.refresh();
|
|
}
|
|
this.a = segment;
|
|
} else if (this.dim == null) {
|
|
if (!segment) {
|
|
this.viewer.toolManager.releaseControl();
|
|
this.viewer.refresh();
|
|
}
|
|
|
|
this.dim = this.dimCreation(this.a, segment);
|
|
let [center, configuration] = this.classify(p.x, p.y);
|
|
if (configuration) {
|
|
this.dim.configuration = configuration;
|
|
}
|
|
if (!center) {
|
|
center = segment.a;
|
|
}
|
|
const [cx, cy] = center;
|
|
this.dim.offset = distance(cx, cy, p.x, p.y);
|
|
this.layer.add(this.dim);
|
|
this.viewer.refresh();
|
|
} else {
|
|
this.viewer.toolManager.releaseControl();
|
|
this.viewer.refresh();
|
|
}
|
|
}
|
|
|
|
classify(px, py) {
|
|
|
|
const line1 = this.dim.a, line2 = this.dim.b;
|
|
|
|
const v1 = [line1.ny, - line1.nx];
|
|
const v2 = [line2.ny, - line2.nx];
|
|
|
|
const isec = findCenter(line1.a, line1.b, line2.a, line2.b, v1[0], v1[1], v2[0], v2[1]);
|
|
if (!isec) {
|
|
return [];
|
|
}
|
|
|
|
const [cx, cy] = isec;
|
|
const v = [px - cx, py - cy];
|
|
|
|
const insideSector = (v, v1, v2) => cross2d(v1, v) > 0 && cross2d(v2, v) < 0;
|
|
|
|
if (insideSector(v, v1, v2)) {
|
|
return [isec, [line1.a, line1.b, line2.a, line2.b]];
|
|
}
|
|
|
|
if (insideSector(v, v2, _negate(v1))) {
|
|
return [isec, [line2.a, line2.b, line1.b, line1.a]];
|
|
}
|
|
_negate(v1);
|
|
|
|
if (insideSector(v, _negate(v1), _negate(v2))) {
|
|
return [isec, [line1.b, line1.a, line2.b, line2.a]];
|
|
}
|
|
_negate(v1);
|
|
_negate(v2);
|
|
|
|
if (insideSector(v, _negate(v2), v1)) {
|
|
return [isec, [line2.b, line2.a, line1.a, line1.b]];
|
|
}
|
|
|
|
|
|
return [isec];
|
|
}
|
|
|
|
}
|
|
|
|
export class AddAngleBetweenDimTool extends AddAngleTool {
|
|
constructor(viewer, layer) {
|
|
super('angle between dimension', viewer, layer, (a, b) => new AngleBetweenDimension(a, b));
|
|
}
|
|
}
|