Offset curve for 2d sketcher. #32

This commit is contained in:
Val Erastov 2016-12-27 23:59:50 -08:00
parent 738505be2b
commit cbfdbae209
6 changed files with 191 additions and 3 deletions

View file

@ -98,12 +98,12 @@ export function rotateInPlace(px, py, angle, out) {
return out;
}
export function polygonOffset( polygon, scale ) {
export function polygonOffsetXY(polygon, scaleX, scaleY) {
const origBBox = new BBox();
const scaledBBox = new BBox();
const result = [];
for (let point of polygon) {
const scaledPoint = new Vector(point.x, point.y)._multiply(scale);
const scaledPoint = new Vector(point.x * scaleX, point.y * scaleY);
result.push(scaledPoint);
origBBox.checkPoint(point);
scaledBBox.checkPoint(scaledPoint);
@ -115,6 +115,21 @@ export function polygonOffset( polygon, scale ) {
return result;
}
export function polygonOffset( polygon, scale ) {
return polygonOffsetXY( polygon, scale, scale );
}
export function polygonOffsetByDelta( polygon, delta ) {
const origBBox = new BBox();
for (let point of polygon) {
origBBox.checkPoint(point);
}
const width = origBBox.width();
const height = origBBox.height();
return polygonOffsetXY(polygon, (width + delta) / width, (height + delta) / height);
}
export function isPointInsidePolygon( inPt, inPolygon ) {
var EPSILON = TOLERANCE;

View file

@ -10,6 +10,7 @@ import {EllipticalArc} from './shapes/elliptical-arc'
import {BezierCurve} from './shapes/bezier-curve'
import {HDimension, VDimension, Dimension, DiameterDimension} from './shapes/dim'
import {Constraints} from './parametric'
import {HashTable} from '../utils/hashmap'
import Vector from '../math/vector'
const Types = {
@ -192,6 +193,10 @@ IO.prototype._loadSketch = function(sketch) {
if (boundaryNeedsUpdate) {
this.addNewBoundaryObjects(boundary, maxEdge);
}
const boundaryLayer = this.viewer.findLayerByName(IO.BOUNDARY_LAYER_NAME);
if (boundaryLayer != null) {
this.linkEndPoints(boundaryLayer.objects);
}
var sketchConstraints = sketch['constraints'];
if (sketchConstraints !== undefined) {
@ -211,6 +216,24 @@ IO.prototype._loadSketch = function(sketch) {
}
};
IO.prototype.linkEndPoints = function(objects) {
const index = HashTable.forVector2d();
for (let obj of objects) {
obj.accept((o) => {
if (o._class == Types.END_POINT) {
const equalPoint = index.get(o);
if (equalPoint == null) {
index.put(o, o);
} else {
o.linked.push(equalPoint);
equalPoint.linked.push(o);
}
}
return true;
})
}
};
IO.prototype.synchLine = function(skobj, edgeObj) {
skobj.a.x = edgeObj.a.x;
skobj.a.y = edgeObj.a.y;

View file

@ -11,6 +11,7 @@ import {FilletTool} from './tools/fillet'
import {EllipseTool} from './tools/ellipse'
import {BezierCurveTool} from './tools/bezier-curve'
import {RectangleTool} from './tools/rectangle'
import {OffsetTool} from './tools/offset'
import {ReferencePointTool} from './tools/origin'
import {InputManager} from './input-manager'
@ -153,6 +154,10 @@ function App2D() {
app.viewer.toolManager.takeControl(new RectangleTool(app.viewer));
}, 'rect');
this.registerAction('offsetTool', "Polygon Offset", function () {
app.viewer.toolManager.takeControl(new OffsetTool(app.viewer));
});
this.registerAction('pan', "Pan", function () {
app.viewer.toolManager.releaseControl();
});

View file

@ -0,0 +1,117 @@
import {Tool} from './tool'
import {Graph} from '../../math/graph'
import {Styles} from '../styles'
export class LoopPickTool extends Tool {
constructor(name, viewer) {
super(name, viewer);
this.loops = new Map();
this.marked = new Set();
this.pickedLoop = null;
}
restart() {
this.sendHint('pick a polygon');
this.reindexLoops();
this.marked.clear();
this.pickedLoop = null;
};
cleanup() {
this.clearMarked();
}
clearMarked() {
for (let obj of this.marked) {
obj.marked = null;
}
this.marked.clear();
}
mark(obj) {
if (!this.marked.has(obj)) {
obj.marked = Styles.SNAP;
this.marked.add(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._class == 'TCAD.TWO.EndPoint' && obj.parent && obj.parent.a && obj.parent.b) {
points.push(obj);
}
return true;
});
const graph = {
connections : (p) => {
const conns = [this.otherEnd(p)];
p.linked.forEach(l => conns.push(this.otherEnd(l)));
return conns;
},
at : function(index) {
return points[index];
},
size : function() {
return points.length;
}
};
const loops = Graph.findAllLoops(graph, (p) => p.id, (a, b) => a.id == b.id);
for (let loop of loops) {
for (let point of loop) {
this.loops.set(point, loop);
}
}
}
mousemove(e) {
this.clearMarked();
this.pickedLoop = null;
const p = this.viewer.screenToModel(e);
this.pickedLoop = this.pickLoop(p);
if (this.pickedLoop != null) {
for (let p of this.pickedLoop) {
this.mark(p.parent);
}
}
this.viewer.refresh();
};
pickLoop(p) {
const pickResult = this.viewer.search(p.x, p.y, 20 / this.viewer.scale, true, false, []);
for (let obj of pickResult) {
for (let 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) {};
}

View file

@ -0,0 +1,27 @@
import {LoopPickTool} from './loop-pick'
import * as math from '../../math/math';
export class OffsetTool extends LoopPickTool {
constructor(viewer) {
super('offset', viewer);
}
onMousedown(e) {
const delta = prompt('offset distance?');
const offsetPolygon = math.polygonOffsetByDelta(this.pickedLoop, parseInt(delta));
const length = offsetPolygon.length;
const segments = [];
for (let p = length - 1, q = 0; q < length; p = q++) {
const a = offsetPolygon[p];
const b = offsetPolygon[q];
const segment = this.viewer.addSegment(a.x, a.y, b.x, b.y, this.viewer.activeLayer);
segments.push(segment);
}
for (var i = 0; i < segments.length; i++) {
this.viewer.parametricManager.linkObjects([segments[i].b, segments[(i + 1) % segments.length].a]);
}
this.viewer.toolManager.releaseControl();
this.viewer.refresh();
}
}

View file

@ -32,7 +32,8 @@
--><button class="btn tbtn act-addEllipse" type="submit" value="">E</button><!--
--><button class="btn tbtn act-addEllipticalArc" type="submit" value="">EA</button><!--
--><button class="btn tbtn act-addBezierCurve sep" type="submit" value="">BZ</button><!--
--><button class="btn tbtn act-addRectangle sep" type="submit" value="">R</button><!--
--><button class="btn tbtn act-addRectangle" type="submit" value="">R</button><!--
--><button class="btn tbtn act-offsetTool sep" type="submit" value="">F</button><!--
--><button class="btn tbtn act-addHDim" style="background-image: url(img/hdim.png);" type="submit" value=""></button><!--
--><button class="btn tbtn act-addVDim" style="background-image: url(img/vdim.png);" type="submit" value=""></button><!--
--><button class="btn tbtn act-addDim" style="background-image: url(img/dim.png);" type="submit" value=""></button><!--