Merge pull request #6527 from HaasJona/fix/path-offset
fix(core): Path.offset(...) improvements
This commit is contained in:
commit
281a04c37f
2 changed files with 56 additions and 3 deletions
|
@ -192,6 +192,11 @@ Path.prototype.bbox = function () {
|
||||||
if (op.to) current = op.to
|
if (op.to) current = op.to
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bbs.length === 0 && current) {
|
||||||
|
// Degenerate case: Line is a point
|
||||||
|
bbs.push(__lineBoundingBox({ from: current, to: current }))
|
||||||
|
}
|
||||||
|
|
||||||
return __bbbbox(bbs)
|
return __bbbbox(bbs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +651,7 @@ Path.prototype.noop = function (id = false) {
|
||||||
Path.prototype.offset = function (distance) {
|
Path.prototype.offset = function (distance) {
|
||||||
distance = __asNumber(distance, 'distance', 'Path.offset', this.log)
|
distance = __asNumber(distance, 'distance', 'Path.offset', this.log)
|
||||||
|
|
||||||
return __pathOffset(this, distance)
|
return __pathOffset(this, distance, this.log)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1391,7 +1396,7 @@ function __offsetLine(from, to, distance, log = false) {
|
||||||
* @param {float} distance - The distance to offset by
|
* @param {float} distance - The distance to offset by
|
||||||
* @return {Path} offsetted - The offsetted Path instance
|
* @return {Path} offsetted - The offsetted Path instance
|
||||||
*/
|
*/
|
||||||
function __pathOffset(path, distance) {
|
function __pathOffset(path, distance, log) {
|
||||||
let offset = []
|
let offset = []
|
||||||
let current
|
let current
|
||||||
let start = false
|
let start = false
|
||||||
|
@ -1428,7 +1433,24 @@ function __pathOffset(path, distance) {
|
||||||
if (!start) start = current
|
if (!start) start = current
|
||||||
}
|
}
|
||||||
|
|
||||||
return closed ? __joinPaths(offset).close() : __joinPaths(offset)
|
let result
|
||||||
|
|
||||||
|
if (offset.length !== 0) {
|
||||||
|
result = __joinPaths(offset)
|
||||||
|
} else {
|
||||||
|
// degenerate case: Original path was likely short, so all the "if (segment)" checks returned false
|
||||||
|
// retry treating the path as a simple straight line from start to end
|
||||||
|
// note: do not call __joinPaths in this branch as this could result in "over-optimizing" this short path
|
||||||
|
let segment = __offsetLine(start, current, distance, path.log)
|
||||||
|
if (segment) {
|
||||||
|
result = segment
|
||||||
|
} else {
|
||||||
|
result = new Path().move(start).line(current)
|
||||||
|
log.warn(`Could not properly calculate offset path, the given path is likely too short.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closed ? result.close() : result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -118,6 +118,28 @@ describe('Path', () => {
|
||||||
expect(round(bbox.bottomRight.x)).to.equal(119.86)
|
expect(round(bbox.bottomRight.x)).to.equal(119.86)
|
||||||
expect(round(bbox.bottomRight.y)).to.equal(43.49)
|
expect(round(bbox.bottomRight.y)).to.equal(43.49)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should offset small curves', () => {
|
||||||
|
const curve = new Path()
|
||||||
|
.move(new Point(0, 0))
|
||||||
|
.curve(new Point(0.1, 0.1), new Point(0.2, 0.2), new Point(0.1, 1.1))
|
||||||
|
const offset = curve.offset(1)
|
||||||
|
const bbox = offset.bbox()
|
||||||
|
expect(round(bbox.bottomRight.x)).to.equal(-0.9)
|
||||||
|
expect(round(bbox.bottomRight.y)).to.equal(1.19)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should offset zero length path', () => {
|
||||||
|
let logged = false
|
||||||
|
const log = { warn: () => (logged = true) }
|
||||||
|
const curve = new Path().__withLog(log).move(new Point(0, 0)).line(new Point(0, 0)).close()
|
||||||
|
expect(logged).to.equal(false)
|
||||||
|
const offset = curve.offset(1)
|
||||||
|
expect(logged).to.equal(true)
|
||||||
|
const bbox = offset.bbox()
|
||||||
|
expect(round(bbox.bottomRight.x)).to.equal(0)
|
||||||
|
expect(round(bbox.bottomRight.y)).to.equal(0)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('length', () => {
|
describe('length', () => {
|
||||||
|
@ -354,6 +376,15 @@ describe('Path', () => {
|
||||||
expect(box.bottomRight.y).to.equal(456)
|
expect(box.bottomRight.y).to.equal(456)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should find the bounding box of an empty path', () => {
|
||||||
|
const path = new Path().move(new Point(123, 456)).close()
|
||||||
|
const box = path.bbox()
|
||||||
|
expect(box.topLeft.x).to.equal(123)
|
||||||
|
expect(box.topLeft.y).to.equal(456)
|
||||||
|
expect(box.bottomRight.x).to.equal(123)
|
||||||
|
expect(box.bottomRight.y).to.equal(456)
|
||||||
|
})
|
||||||
|
|
||||||
it('Should reverse a path', () => {
|
it('Should reverse a path', () => {
|
||||||
const test = new Path()
|
const test = new Path()
|
||||||
.move(new Point(123, 456))
|
.move(new Point(123, 456))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue