diff --git a/python/commands/board/outline.py b/python/commands/board/outline.py index d003213..9f34549 100644 --- a/python/commands/board/outline.py +++ b/python/commands/board/outline.py @@ -30,13 +30,33 @@ class BoardOutlineCommands: shape = params.get("shape", "rectangle") width = params.get("width") height = params.get("height") - center_x = params.get("centerX", 0) - center_y = params.get("centerY", 0) radius = params.get("radius") - corner_radius = params.get("cornerRadius", 0) + # Accept both "cornerRadius" and "radius" (schema uses "radius" for rounded_rectangle) + corner_radius = params.get("cornerRadius", params.get("radius", 0) if shape == "rounded_rectangle" else 0) points = params.get("points", []) unit = params.get("unit", "mm") + # Position: accept top-left corner (x/y) or center (centerX/centerY). + # Default: top-left at (0,0) so the board occupies positive coordinate space + # and is consistent with component placement coordinates. + x = params.get("x") + y = params.get("y") + if x is not None or y is not None: + ox = x if x is not None else 0.0 + oy = y if y is not None else 0.0 + center_x = ox + (width or 0) / 2.0 + center_y = oy + (height or 0) / 2.0 + else: + raw_cx = params.get("centerX") + raw_cy = params.get("centerY") + if raw_cx is not None or raw_cy is not None: + center_x = raw_cx if raw_cx is not None else 0.0 + center_y = raw_cy if raw_cy is not None else 0.0 + else: + # No position given → place top-left at (0,0) + center_x = (width or 0) / 2.0 + center_y = (height or 0) / 2.0 + if shape not in ["rectangle", "circle", "polygon", "rounded_rectangle"]: return { "success": False, diff --git a/python/kicad_interface.py b/python/kicad_interface.py index 4fba299..9b9ac94 100644 --- a/python/kicad_interface.py +++ b/python/kicad_interface.py @@ -2131,7 +2131,17 @@ print("ok") return {"success": False, "message": str(e)} def _ipc_add_board_outline(self, params): - """IPC handler for add_board_outline - adds board edge with real-time UI update""" + """IPC handler for add_board_outline - adds board edge with real-time UI update. + Rounded rectangles are delegated to the SWIG path because the IPC BoardSegment + type cannot represent arcs; the SWIG path writes directly to the .kicad_pcb file + and correctly generates PCB_SHAPE arcs for rounded corners. + """ + shape = params.get("shape", "rectangle") + if shape == "rounded_rectangle": + # IPC path only supports straight segments — fall back to SWIG for arcs + logger.info("_ipc_add_board_outline: delegating rounded_rectangle to SWIG path for arc support") + return self.board_commands.add_board_outline(params) + try: from kipy.board_types import BoardSegment from kipy.geometry import Vector2 diff --git a/python/schemas/tool_schemas.py b/python/schemas/tool_schemas.py index 7a752b0..d692da6 100644 --- a/python/schemas/tool_schemas.py +++ b/python/schemas/tool_schemas.py @@ -110,7 +110,7 @@ BOARD_TOOLS = [ { "name": "add_board_outline", "title": "Add Board Outline", - "description": "Adds a board outline shape (rectangle, rounded rectangle, circle, or polygon) on the Edge.Cuts layer.", + "description": "Adds a board outline shape (rectangle, rounded_rectangle, circle, or polygon) on the Edge.Cuts layer. By default the board top-left corner is placed at (0, 0) so all coordinates are positive. Use x/y to set a different top-left corner position.", "inputSchema": { "type": "object", "properties": { @@ -129,19 +129,26 @@ BOARD_TOOLS = [ "description": "Height in mm (for rectangle/rounded_rectangle)", "minimum": 1 }, + "x": { + "type": "number", + "description": "X coordinate of the top-left corner in mm (default: 0). Board extends from x to x+width." + }, + "y": { + "type": "number", + "description": "Y coordinate of the top-left corner in mm (default: 0). Board extends from y to y+height." + }, "radius": { "type": "number", - "description": "Radius in mm (for circle) or corner radius (for rounded_rectangle)", + "description": "Corner radius in mm for rounded_rectangle, or radius for circle", "minimum": 0 }, "points": { "type": "array", - "description": "Array of [x, y] coordinates in mm (for polygon)", + "description": "Array of {x, y} point objects in mm (for polygon shape only)", "items": { - "type": "array", - "items": {"type": "number"}, - "minItems": 2, - "maxItems": 2 + "type": "object", + "properties": {"x": {"type": "number"}, "y": {"type": "number"}}, + "required": ["x", "y"] }, "minItems": 3 }