UNPKG

kipm

Version:

KiCad component package manager

380 lines (345 loc) 11 kB
// parameters_kicad_footprint.js // ---------------------------- FOOTPRINT PART ---------------------------- // KiCad footprint template constants const KI_MODULE_INFO = "(module {package_lib}:{package_name} (layer F.Cu) (tedit {edit})\n"; const KI_DESCRIPTION = `\t(descr "{datasheet_link}, generated with easyeda2kicad.py on {date}")\n`; const KI_TAGS_INFO = `\t(tags "{tag}")\n`; const KI_FP_TYPE = "\t(attr {component_type})\n"; const KI_REFERENCE = `\t(fp_text reference REF** (at {pos_x} {pos_y}) (layer F.SilkS) \t\t(effects (font (size 1 1) (thickness 0.15))) \t)\n`; const KI_PACKAGE_VALUE = `\t(fp_text value {package_name} (at {pos_x} {pos_y}) (layer F.Fab) \t\t(effects (font (size 1 1) (thickness 0.15))) \t)\n`; const KI_FAB_REF = `\t(fp_text user %R (at 0 0) (layer F.Fab) \t\t(effects (font (size 1 1) (thickness 0.15))) \t)\n`; const KI_END_FILE = ")"; // Note: Adjusted KI_PAD, KI_LINE, etc., so that they don’t include extra newlines. const KI_PAD = `\t(pad {number} {type} {shape} (at {pos_x:.2f} {pos_y:.2f} {orientation:.2f}) (size {width:.2f} {height:.2f}) (layers {layers}){drill}{polygon})\n`; const KI_LINE = `\t(fp_line (start {start_x:.2f} {start_y:.2f}) (end {end_x:.2f} {end_y:.2f}) (layer {layers}) (width {stroke_width:.2f}))\n`; const KI_HOLE = `\t(pad "" thru_hole circle (at {pos_x:.2f} {pos_y:.2f}) (size {size:.2f} {size:.2f}) (drill {size:.2f}) (layers *.Cu *.Mask))\n`; const KI_VIA = `\t(pad "" thru_hole circle (at {pos_x:.2f} {pos_y:.2f}) (size {diameter:.2f} {diameter:.2f}) (drill {size:.2f}) (layers *.Cu *.Paste *.Mask))\n`; const KI_CIRCLE = `\t(fp_circle (center {cx:.2f} {cy:.2f}) (end {end_x:.2f} {end_y:.2f}) (layer {layers}) (width {stroke_width:.2f}))\n`; const KI_ARC = `\t(fp_arc (start {start_x:.2f} {start_y:.2f}) (end {end_x:.2f} {end_y:.2f}) (angle {angle:.2f}) (layer {layers}) (width {stroke_width:.2f}))\n`; const KI_TEXT = `\t(fp_text user {text} (at {pos_x:.2f} {pos_y:.2f} {orientation:.2f}) (layer {layers}){display}\n\t\t(effects (font (size {font_size:.2f} {font_size:.2f}) (thickness {thickness:.2f})) (justify left{mirror}))\n\t)\n`; const KI_MODEL_3D = `\t(model "{file_3d}"\n\t\t(offset (xyz {pos_x:.3f} {pos_y:.3f} {pos_z:.3f}))\n\t\t(scale (xyz 1 1 1))\n\t\t(rotate (xyz {rot_x:.0f} {rot_y:.0f} {rot_z:.0f}))\n\t)\n`; const KI_RECT = `\t(fp_rect (start {start_x:.2f} {start_y:.2f}) (end {end_x:.2f} {end_y:.2f}) (layer {layers}) (width {stroke_width:.2f}))\n`; // Pad shape and layer definitions const KI_PAD_SHAPE = { "ELLIPSE": "circle", "RECT": "rect", "OVAL": "oval", "POLYGON": "custom", }; const KI_PAD_LAYER = { 1: "F.Cu F.Paste F.Mask", 2: "B.Cu B.Paste B.Mask", 3: "F.SilkS", 11: "*.Cu *.Paste *.Mask", 13: "F.Fab", 15: "Dwgs.User", }; const KI_PAD_LAYER_THT = { 1: "F.Cu F.Mask", 2: "B.Cu B.Mask", 3: "F.SilkS", 11: "*.Cu *.Mask", 13: "F.Fab", 15: "Dwgs.User", }; const KI_LAYERS = { 1: "F.Cu", 2: "B.Cu", 3: "F.SilkS", 4: "B.SilkS", 5: "F.Paste", 6: "B.Paste", 7: "F.Mask", 8: "B.Mask", 10: "Edge.Cuts", 11: "Edge.Cuts", 12: "Cmts.User", 13: "F.Fab", 14: "B.Fab", 15: "Dwgs.User", 101: "F.Fab", }; // ---------------- Helper Function ---------------- // Rounds all numeric properties on an object to two decimals. function roundFloatValues(obj) { for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { if (typeof obj[key] === "number") { obj[key] = Math.round(obj[key] * 100) / 100; } } } } // ---------------- Data Classes ---------------- // PAD class KiFootprintPad { constructor({ type, shape, pos_x, pos_y, width, height, layers, number, drill, orientation, polygon, }) { this.type = type; this.shape = shape; this.pos_x = pos_x; this.pos_y = pos_y; this.width = width; this.height = height; this.layers = layers; this.number = number; this.drill = drill; this.orientation = orientation; this.polygon = polygon; roundFloatValues(this); } } // TRACK class KiFootprintTrack { constructor({ points_start_x = [], points_start_y = [], points_end_x = [], points_end_y = [], stroke_width = 0, layers = "", } = {}) { this.points_start_x = points_start_x; this.points_start_y = points_start_y; this.points_end_x = points_end_x; this.points_end_y = points_end_y; this.stroke_width = stroke_width; this.layers = layers; } } // HOLE class KiFootprintHole { constructor({ pos_x, pos_y, size }) { this.pos_x = pos_x; this.pos_y = pos_y; this.size = size; roundFloatValues(this); } } // CIRCLE class KiFootprintCircle { constructor({ cx, cy, end_x, end_y, layers, stroke_width }) { this.cx = cx; this.cy = cy; this.end_x = end_x; this.end_y = end_y; this.layers = layers; this.stroke_width = stroke_width; roundFloatValues(this); } } // RECTANGLE – inherits from KiFootprintTrack class KiFootprintRectangle extends KiFootprintTrack { constructor(options = {}) { super(options); } } // ARC class KiFootprintArc { constructor({ start_x, start_y, end_x, end_y, angle, layers, stroke_width }) { this.start_x = start_x; this.start_y = start_y; this.end_x = end_x; this.end_y = end_y; this.angle = angle; this.layers = layers; this.stroke_width = stroke_width; roundFloatValues(this); } getBoundingBox() { // For nearly complete circles if (Math.abs(this.angle) >= 359 && Math.abs(this.start_y) === 0) { const centerX = this.start_x; // center is at start_x const centerY = 0; // center is at y=0 const radius = Math.abs(this.end_y); // radius is the distance to end_y // Account for stroke width const totalRadius = radius + this.stroke_width / 2; return { min_x: centerX - totalRadius, max_x: centerX + totalRadius, min_y: centerY - totalRadius, max_y: centerY + totalRadius }; } // For partial arcs const dx = this.end_x - this.start_x; const dy = this.end_y - this.start_y; const angleRad = (this.angle / 10) * Math.PI / 180; // Calculate center of arc using start and end points and angle const chord = Math.sqrt(dx * dx + dy * dy); const radius = chord / (2 * Math.sin(angleRad / 2)); // Find all extreme points const points = [ [this.start_x, this.start_y], [this.end_x, this.end_y] ]; // Check intermediate points if arc crosses 0°, 90°, 180°, or 270° // TODO: Add logic for partial arcs if needed let minX = Math.min(...points.map(p => p[0])); let maxX = Math.max(...points.map(p => p[0])); let minY = Math.min(...points.map(p => p[1])); let maxY = Math.max(...points.map(p => p[1])); return { min_x: minX, max_x: maxX, min_y: minY, max_y: maxY }; } } // TEXT class KiFootprintText { constructor({ pos_x, pos_y, orientation, text, layers, font_size, thickness, display, mirror, }) { this.pos_x = pos_x; this.pos_y = pos_y; this.orientation = orientation; this.text = text; this.layers = layers; this.font_size = font_size; this.thickness = thickness; this.display = display; this.mirror = mirror; roundFloatValues(this); } } // VIA class KiFootprintVia { constructor({ pos_x, pos_y, size, diameter }) { this.pos_x = pos_x; this.pos_y = pos_y; this.size = size; this.diameter = diameter; roundFloatValues(this); } } // SOLID REGION class KiFootprintSolidRegion { constructor({ name = "" } = {}) { this.name = name; } } // COPPER AREA class KiFootprintCopperArea { constructor({ name = "" } = {}) { this.name = name; } } // FOOTPRINT INFO class KiFootprintInfo { constructor({ name, fp_type }) { this.name = name; this.fp_type = fp_type; } } // 3D MODEL BASE class Ki3dModelBase { constructor({ x = 0.0, y = 0.0, z = 0.0 } = {}) { this.x = x; this.y = y; this.z = z; } } // 3D MODEL class Ki3dModel { constructor({ name, translation, rotation, raw_wrl = null }) { this.name = name; this.translation = translation; this.rotation = rotation; this.raw_wrl = raw_wrl; } } // FOOTPRINT class KiFootprint { constructor({ info, model_3d, pads = [], tracks = [], vias = [], holes = [], circles = [], arcs = [], rectangles = [], texts = [], solid_regions = [], copper_areas = [], } = {}) { this.info = info; this.model_3d = model_3d; this.pads = pads; this.tracks = tracks; this.vias = vias; this.holes = holes; this.circles = circles; this.arcs = arcs; this.rectangles = rectangles; this.texts = texts; this.solid_regions = solid_regions; this.copper_areas = copper_areas; } } // ---------------- Exports ---------------- module.exports = { KI_MODULE_INFO, KI_DESCRIPTION, KI_TAGS_INFO, KI_FP_TYPE, KI_REFERENCE, KI_PACKAGE_VALUE, KI_FAB_REF, KI_END_FILE, KI_PAD, KI_LINE, KI_HOLE, KI_VIA, KI_CIRCLE, KI_ARC, KI_TEXT, KI_MODEL_3D, KI_PAD_SHAPE, KI_PAD_LAYER, KI_PAD_LAYER_THT, KI_LAYERS, KI_RECT, KiFootprintPad, KiFootprintTrack, KiFootprintHole, KiFootprintCircle, KiFootprintRectangle, KiFootprintArc, KiFootprintText, KiFootprintVia, KiFootprintSolidRegion, KiFootprintCopperArea, KiFootprintInfo, Ki3dModelBase, Ki3dModel, KiFootprint, };