circuit-to-canvas 0.0.45 → 0.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +530 -163
- package/lib/drawer/CircuitToCanvasDrawer.ts +1 -5
- package/lib/drawer/elements/pcb-hole.ts +248 -61
- package/lib/drawer/elements/pcb-plated-hole.ts +234 -107
- package/lib/drawer/elements/pcb-smtpad.ts +43 -21
- package/lib/drawer/elements/soldermask-margin.ts +130 -0
- package/package.json +1 -1
- package/tests/board-snapshot/__snapshots__/usb-c-flashlight-board.snap.png +0 -0
- package/tests/elements/__snapshots__/board-with-elements.snap.png +0 -0
- package/tests/elements/__snapshots__/custom-outline-board.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-board.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-comprehensive-soldermask-margin.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-fabrication-note-dimension.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-hole-soldermask-margin.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-keepout-layer-filter.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-keepout-multiple-layers.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-keepout-rect-and-circle.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-keepout-with-group-id.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-note-dimension-with-offset.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-plated-hole-soldermask-margin.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-silkscreen-oval.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-smtpad-soldermask-margin.snap.png +0 -0
- package/tests/elements/pcb-comprehensive-soldermask-margin.test.ts +1281 -0
- package/tests/elements/pcb-hole-soldermask-margin.test.ts +5 -5
- package/tests/elements/pcb-plated-hole-soldermask-margin.test.ts +8 -8
- package/tests/elements/pcb-smtpad-soldermask-margin.test.ts +0 -6
- package/tests/shapes/__snapshots__/dimension-line.snap.png +0 -0
|
@@ -324,3 +324,133 @@ export function drawSoldermaskRingForOval(
|
|
|
324
324
|
|
|
325
325
|
ctx.restore()
|
|
326
326
|
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Offsets polygon points by a given distance (positive = outward, negative = inward)
|
|
330
|
+
*/
|
|
331
|
+
export function offsetPolygonPoints(
|
|
332
|
+
points: Array<{ x: number; y: number }>,
|
|
333
|
+
offset: number,
|
|
334
|
+
): Array<{ x: number; y: number }> {
|
|
335
|
+
if (points.length < 3 || offset === 0) return points
|
|
336
|
+
|
|
337
|
+
// Calculate polygon centroid
|
|
338
|
+
let centerX = 0
|
|
339
|
+
let centerY = 0
|
|
340
|
+
for (const point of points) {
|
|
341
|
+
centerX += point.x
|
|
342
|
+
centerY += point.y
|
|
343
|
+
}
|
|
344
|
+
centerX /= points.length
|
|
345
|
+
centerY /= points.length
|
|
346
|
+
|
|
347
|
+
const result: Array<{ x: number; y: number }> = []
|
|
348
|
+
|
|
349
|
+
for (const point of points) {
|
|
350
|
+
// Calculate vector from center to point
|
|
351
|
+
const vectorX = point.x - centerX
|
|
352
|
+
const vectorY = point.y - centerY
|
|
353
|
+
|
|
354
|
+
// Calculate distance from center
|
|
355
|
+
const distance = Math.sqrt(vectorX * vectorX + vectorY * vectorY)
|
|
356
|
+
|
|
357
|
+
if (distance > 0) {
|
|
358
|
+
// Normalize vector and offset
|
|
359
|
+
const normalizedX = vectorX / distance
|
|
360
|
+
const normalizedY = vectorY / distance
|
|
361
|
+
|
|
362
|
+
result.push({
|
|
363
|
+
x: point.x + normalizedX * offset,
|
|
364
|
+
y: point.y + normalizedY * offset,
|
|
365
|
+
})
|
|
366
|
+
} else {
|
|
367
|
+
// Point is at center, offset in arbitrary direction
|
|
368
|
+
result.push({
|
|
369
|
+
x: point.x + offset,
|
|
370
|
+
y: point.y,
|
|
371
|
+
})
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return result
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Draws a soldermask ring for polygon shapes with negative margin
|
|
380
|
+
* (soldermask appears inside the pad boundary)
|
|
381
|
+
*/
|
|
382
|
+
export function drawSoldermaskRingForPolygon(
|
|
383
|
+
ctx: CanvasContext,
|
|
384
|
+
points: Array<{ x: number; y: number }>,
|
|
385
|
+
margin: number,
|
|
386
|
+
realToCanvasMat: Matrix,
|
|
387
|
+
soldermaskColor: string,
|
|
388
|
+
padColor: string,
|
|
389
|
+
): void {
|
|
390
|
+
if (points.length < 3 || margin >= 0) return
|
|
391
|
+
|
|
392
|
+
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a)
|
|
393
|
+
|
|
394
|
+
// For negative margins, outer is pad boundary, inner is contracted by margin
|
|
395
|
+
// Use source-atop so the ring only appears on the pad
|
|
396
|
+
const prevCompositeOp = ctx.globalCompositeOperation
|
|
397
|
+
if (ctx.globalCompositeOperation !== undefined) {
|
|
398
|
+
ctx.globalCompositeOperation = "source-atop"
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Draw outer polygon filled (at pad boundary)
|
|
402
|
+
ctx.beginPath()
|
|
403
|
+
const canvasPoints = points.map((p) =>
|
|
404
|
+
applyToPoint(realToCanvasMat, [p.x, p.y]),
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
const firstPoint = canvasPoints[0]
|
|
408
|
+
if (firstPoint) {
|
|
409
|
+
const [firstX, firstY] = firstPoint
|
|
410
|
+
ctx.moveTo(firstX, firstY)
|
|
411
|
+
|
|
412
|
+
for (let i = 1; i < canvasPoints.length; i++) {
|
|
413
|
+
const point = canvasPoints[i]
|
|
414
|
+
if (point) {
|
|
415
|
+
const [x, y] = point
|
|
416
|
+
ctx.lineTo(x, y)
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
ctx.closePath()
|
|
420
|
+
ctx.fillStyle = soldermaskColor
|
|
421
|
+
ctx.fill()
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Reset composite operation and restore pad color in inner area
|
|
425
|
+
if (ctx.globalCompositeOperation !== undefined) {
|
|
426
|
+
ctx.globalCompositeOperation = prevCompositeOp || "source-over"
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Restore pad color in inner polygon (contracted by margin)
|
|
430
|
+
const innerPoints = offsetPolygonPoints(points, margin)
|
|
431
|
+
if (innerPoints.length >= 3) {
|
|
432
|
+
ctx.beginPath()
|
|
433
|
+
const innerCanvasPoints = innerPoints.map((p) =>
|
|
434
|
+
applyToPoint(realToCanvasMat, [p.x, p.y]),
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
const firstInnerPoint = innerCanvasPoints[0]
|
|
438
|
+
if (firstInnerPoint) {
|
|
439
|
+
const [firstX, firstY] = firstInnerPoint
|
|
440
|
+
ctx.moveTo(firstX, firstY)
|
|
441
|
+
|
|
442
|
+
for (let i = 1; i < innerCanvasPoints.length; i++) {
|
|
443
|
+
const point = innerCanvasPoints[i]
|
|
444
|
+
if (point) {
|
|
445
|
+
const [x, y] = point
|
|
446
|
+
ctx.lineTo(x, y)
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
ctx.closePath()
|
|
450
|
+
ctx.fillStyle = padColor
|
|
451
|
+
ctx.fill()
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
ctx.restore()
|
|
456
|
+
}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|