From 50e7ef906af80cac1cf019a8556c786807bb22ba Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sat, 27 Jul 2024 22:35:01 -0400 Subject: [PATCH] add support for open poly line width and miter distances --- src/geo/polygon.js | 3 ++- src/load/svg.js | 4 ++++ src/mesh/api.js | 4 ++-- src/mesh/build.js | 10 +++++----- src/mesh/sketch.js | 12 ++++++++---- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/geo/polygon.js b/src/geo/polygon.js index c6988b17..6d6084a2 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -1701,9 +1701,10 @@ class Polygon { * @param {'square'|'round'|'miter'} type * @returns {Polygon[]} */ - offset_open(distance, type = 'miter') { + offset_open(distance, type = 'miter', miterLimit = 2) { if (this.isOpen()) { let coff = new ClipperOffset(), + dudd = (coff.MiterLimit = miterLimit), tree = new PolyTree(), entt = { 'square' : EndType.etOpenSquare, diff --git a/src/load/svg.js b/src/load/svg.js index 14ce201c..c663ba6b 100644 --- a/src/load/svg.js +++ b/src/load/svg.js @@ -32,6 +32,8 @@ function parse(text, opt = { soup: true }) { let path = paths[i]; let shapes = path.toShapes(true); let type = path.userData?.node?.nodeName; + let width = path.userData?.style?.strokeWidth; + let miter = path.userData?.style?.strokeMiterLimit; if (fromSoup) { for (let node of shapes) { let { shape, holes } = node.extractPoints(); @@ -39,6 +41,8 @@ function parse(text, opt = { soup: true }) { let poly = base.newPolygon().addPoints(path.map(p => base.newPoint(p.x, -p.y, 0))); if (poly.appearsClosed()) poly.points.pop(); if (type === 'polyline') poly.setOpen(true); + if (width) poly.width = width; + if (miter) poly.miter = miter; polys.push(poly); } } diff --git a/src/mesh/api.js b/src/mesh/api.js index d9b8f46c..28d26576 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -466,7 +466,7 @@ let sketch = { h.button({ _: "create", onclick() { const { _height, _chamtop, _chambot } = api.modal.bound; sketch.extrude({ - selection: sketch.selected.count() > 0, + selection: sketch.selection.count() > 0, ...opt, height: parseFloat(_height.value), chamfer_top: parseFloat(_chamtop.value), @@ -1271,7 +1271,7 @@ const prefs = { select: [] }, sketch: { - close_poly: false, + open_close: false, open_thick: 1, open_type: 'miter' }, diff --git a/src/mesh/build.js b/src/mesh/build.js index a9165c2d..39a6671f 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -317,12 +317,12 @@ api.settings = function() { h.label({ class: "header", _: 'open poly'}), h.label('auto close'), h.input({ type: "checkbox", - onchange: ev => prefs.save( (sketch.close_poly = !sketch.close_poly) && srr() ), - [ sketch.close_poly === true ? 'checked' : 'unchecked' ] : 1 + onchange: ev => prefs.save( ((sketch.open_close = !sketch.open_close) || true) && srr() ), + [ sketch.open_close === true ? 'checked' : 'unchecked' ] : 1 }), - h.label('thickness'), - h.input({ type: "text", size: 5, value: parseFloat(sketch.open_thick || 1), - onchange: ev => prefs.save( (sketch.open_thick = parseFloat(ev.target.value)) && srr() ) + h.label('width'), + h.input({ type: "text", size: 5, value: parseFloat(sketch.open_width || 1), + onchange: ev => prefs.save( (sketch.open_width = parseFloat(ev.target.value)) && srr() ) }), h.label('type'), h.select({ type: "text", value: sketch.open_type, diff --git a/src/mesh/sketch.js b/src/mesh/sketch.js index 49faeafd..257106d3 100644 --- a/src/mesh/sketch.js +++ b/src/mesh/sketch.js @@ -153,7 +153,7 @@ mesh.sketch = class MeshSketch extends mesh.object { }, count() { - return sketch.selection.mesh_items().length; + return sketch.items.filter(i => i.selected).length; }, all() { @@ -431,6 +431,8 @@ mesh.sketch = class MeshSketch extends mesh.object { delete opt.poly; this.add_item({ type: "polygon", + width: poly.width, + miter: poly.miter, selected: true, ...Object.assign({}, { center: {x:0, y:0, z:0} }, opt), ...poly.toObject() @@ -529,8 +531,8 @@ class SketchItem { let bump = 0.0025; let { item, sketch, order } = this; let { material } = mesh; - let { type, center, width, height, radius, points, spacing, poly, selected } = item; - let { close_poly, open_thick, open_type } = api.prefs.map.sketch; + let { type, center, width, height, miter, radius, points, spacing, poly, selected } = item; + let { open_close, open_width, open_type } = api.prefs.map.sketch; if (type === 'circle') { let circumference = 2 * Math.PI * radius; points = points || Math.floor(circumference / (spacing || 1)); @@ -540,7 +542,9 @@ class SketchItem { } else if (type === 'polygon') { poly = newPolygon().fromObject(item); poly.move(center); - if (poly.isOpen() && !close_poly) poly = poly.offset_open(open_thick, open_type)[0]; + if (poly.isOpen() && open_close !== true) { + poly = poly.offset_open(width || open_width || 1, open_type, miter)[0]; + } } else { throw `invalid sketch type: ${type}`; }