diff --git a/python/commands/wire_manager.py b/python/commands/wire_manager.py index 8ff9267..87d778d 100644 --- a/python/commands/wire_manager.py +++ b/python/commands/wire_manager.py @@ -340,6 +340,72 @@ class WireManager: logger.error(traceback.format_exc()) return False + @staticmethod + def delete_wire(schematic_path: Path, start_point: List[float], end_point: List[float], + tolerance: float = 0.5) -> bool: + """ + Delete a wire from the schematic matching given start/end coordinates. + + Args: + schematic_path: Path to .kicad_sch file + start_point: [x, y] coordinates for wire start + end_point: [x, y] coordinates for wire end + tolerance: Maximum coordinate difference to consider a match (mm) + + Returns: + True if a wire was found and removed, False otherwise + """ + try: + with open(schematic_path, 'r', encoding='utf-8') as f: + sch_content = f.read() + + sch_data = sexpdata.loads(sch_content) + + sx, sy = start_point + ex, ey = end_point + + for i, item in enumerate(sch_data): + if not (isinstance(item, list) and len(item) > 0 and item[0] == Symbol('wire')): + continue + + # Extract pts from the wire s-expression + pts_list = None + for part in item[1:]: + if isinstance(part, list) and len(part) > 0 and part[0] == Symbol('pts'): + pts_list = part + break + + if pts_list is None: + continue + + xy_points = [p for p in pts_list[1:] if isinstance(p, list) and len(p) >= 3 and p[0] == Symbol('xy')] + if len(xy_points) < 2: + continue + + x1, y1 = float(xy_points[0][1]), float(xy_points[0][2]) + x2, y2 = float(xy_points[-1][1]), float(xy_points[-1][2]) + + match_fwd = (abs(x1 - sx) < tolerance and abs(y1 - sy) < tolerance and + abs(x2 - ex) < tolerance and abs(y2 - ey) < tolerance) + match_rev = (abs(x1 - ex) < tolerance and abs(y1 - ey) < tolerance and + abs(x2 - sx) < tolerance and abs(y2 - sy) < tolerance) + + if match_fwd or match_rev: + del sch_data[i] + with open(schematic_path, 'w', encoding='utf-8') as f: + f.write(sexpdata.dumps(sch_data)) + logger.info(f"Deleted wire from {start_point} to {end_point}") + return True + + logger.warning(f"No matching wire found for {start_point} to {end_point}") + return False + + except Exception as e: + logger.error(f"Error deleting wire: {e}") + import traceback + logger.error(traceback.format_exc()) + return False + @staticmethod def create_orthogonal_path(start: List[float], end: List[float], prefer_horizontal_first: bool = True) -> List[List[float]]: diff --git a/python/kicad_interface.py b/python/kicad_interface.py index f1a5466..b8f8935 100644 --- a/python/kicad_interface.py +++ b/python/kicad_interface.py @@ -1898,43 +1898,13 @@ class KiCADInterface: if not schematic_path: return {"success": False, "message": "schematicPath is required"} - schematic = SchematicManager.load_schematic(schematic_path) - if not schematic: - return {"success": False, "message": "Failed to load schematic"} + from pathlib import Path + from commands.wire_manager import WireManager + start_point = [start.get("x", 0), start.get("y", 0)] + end_point = [end.get("x", 0), end.get("y", 0)] - if not hasattr(schematic, "wire"): - return {"success": False, "message": "Schematic has no wires"} - - tolerance = 0.5 - wire_to_remove = None - - for wire in schematic.wire: - if not hasattr(wire, "pts") or not hasattr(wire.pts, "xy"): - continue - points = [] - for point in wire.pts.xy: - if hasattr(point, "value"): - points.append([float(point.value[0]), float(point.value[1])]) - - if len(points) < 2: - continue - - sx, sy = start.get("x", 0), start.get("y", 0) - ex, ey = end.get("x", 0), end.get("y", 0) - - # Check both directions - match_fwd = (abs(points[0][0] - sx) < tolerance and abs(points[0][1] - sy) < tolerance and - abs(points[-1][0] - ex) < tolerance and abs(points[-1][1] - ey) < tolerance) - match_rev = (abs(points[0][0] - ex) < tolerance and abs(points[0][1] - ey) < tolerance and - abs(points[-1][0] - sx) < tolerance and abs(points[-1][1] - sy) < tolerance) - - if match_fwd or match_rev: - wire_to_remove = wire - break - - if wire_to_remove: - schematic.wire._elements.remove(wire_to_remove) - SchematicManager.save_schematic(schematic, schematic_path) + deleted = WireManager.delete_wire(Path(schematic_path), start_point, end_point) + if deleted: return {"success": True} else: return {"success": False, "message": "No matching wire found"}