package de.ph87.electro.circuit; import de.ph87.electro.circuit.node.Node; import de.ph87.electro.circuit.part.Orientation; import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.PartNode; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import static de.ph87.electro.CONFIG.*; import static java.lang.Math.round; public class CircuitPainter { public static BufferedImage draw(final Circuit circuit, final int w, final int h) { final BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); final Graphics2D g = img.createGraphics(); draw(g, circuit, w, h); return img; } public static void draw(final Graphics2D g, final Circuit circuit, final int w, final int h) { g.setTransform(new AffineTransform()); drawBack(g, w, h); drawParts(circuit, g); g.setTransform(new AffineTransform()); drawRaster(g, w, h); drawWires(circuit, g); drawVoltages(circuit, g); } private static void drawBack(final Graphics2D g, final int w, final int h) { g.setColor(Color.white); g.fillRect(0, 0, w, h); } private static void drawParts(final Circuit circuit, final Graphics2D g) { circuit.streamParts().forEach(part -> { g.setTransform(part.getTransform()); part.draw(g); }); } private static void drawRaster(final Graphics2D g, final int w, final int h) { g.setStroke(RASTER_STROKE); g.setColor(RASTER_COLOR); for (int x = 0; x < w; x += RASTER) { g.drawLine(x, 0, x, h); } for (int y = 0; y < h; y += RASTER) { g.drawLine(0, y, w, y); } } private static void drawWires(final Circuit circuit, final Graphics2D g) { circuit.streamWires().forEach(wire -> wire.draw(g)); } private static void drawVoltages(final Circuit circuit, final Graphics2D g) { if (!SHOW_NODE_VOLTAGES && !SHOW_NODE_NAMES) { return; } g.setColor(Color.BLACK); g.setFont(LABEL_FONT); final int third = g.getFont().getSize() / 3; for (Part part : circuit.getParts()) { for (final Node node : part.getNodes()) { final Point absolute = node.getPosition(); if (SHOW_NODE_NAMES) { int offsetY = third; if (SHOW_NODE_VOLTAGES) { offsetY -= third; } final String string = node.getName(); final Rectangle2D bounds = g.getFontMetrics().getStringBounds(string, g); g.drawString(string, absolute.x - (int) (bounds.getWidth() / 2), absolute.y + offsetY); } if (SHOW_NODE_VOLTAGES) { int offsetY = third; if (SHOW_NODE_NAMES) { offsetY += 2 * third; } final String string = "%.1fV".formatted(node.getVoltage()); final Rectangle2D bounds = g.getFontMetrics().getStringBounds(string, g); g.drawString(string, absolute.x - (int) (bounds.getWidth() / 2), absolute.y + offsetY); } } } } public static void drawLine(final Graphics2D g, final PartNode a, final PartNode b, final Color color, final Stroke stroke) { drawLine(g, a.getInside(), b.getInside(), color, stroke); } public static void drawLine(final Graphics2D g, final PartNode a, final Point b, final Color color, final Stroke stroke) { drawLine(g, a.getInside(), b, color, stroke); } public static void drawLine(final Graphics2D g, final Point a, final Point b, final Color color, final Stroke stroke) { drawLine(g, a.x, a.y, b.x, b.y, color, stroke); } public static void drawLine(final Graphics2D g, final int x0, final int y0, final int x1, final int y1, final Color color, final Stroke stroke) { g.setColor(color); g.setStroke(stroke); g.drawLine(x0, y0, x1, y1); } public static void fillRect(final Graphics2D g, final int x0, final int y0, final int x1, final int y1, final Color color) { g.setColor(color); g.fillRect(x0, y0, x1, y1); } public static void drawCircle(final Graphics2D g, final Point center, final int radius, final double degreesOffset, final double degreesRange, final Color border, final Stroke stroke, final Color fill) { drawCircle(g, center.x, center.y, radius, border, stroke, fill, degreesOffset, degreesRange); } public static void drawCircle(final Graphics2D g, final int x, final int y, final int radius, final Color border, final Stroke stroke, final Color fill, final double degreesOffset, final double degreesRange) { if (fill != null) { g.setColor(fill); g.fillArc(x - radius, y - radius, 2 * radius, 2 * radius, (int) round(degreesOffset), (int) round(degreesRange)); } if (border != null && stroke != null) { g.setColor(border); g.setStroke(stroke); g.drawArc(x - radius, y - radius, 2 * radius, 2 * radius, (int) round(degreesOffset), (int) round(degreesRange)); } } public static void drawText(final Graphics2D g, final Font font, final String text, final int x, int y, final Color color, final Orientation orientation) { final AffineTransform transformBackup = g.getTransform(); if (orientation == Orientation.R180) { g.rotate(orientation.getRadians(), P50, P50); y = RASTER - y; } g.setFont(font); g.setColor(color); final Rectangle2D bounds = g.getFontMetrics().getStringBounds(text, g); final int xx = (int) round(x - bounds.getWidth() / 2); final int yy = (int) round(y - bounds.getHeight() / 2 + font.getSize()); g.drawString(text, xx, yy); g.setTransform(transformBackup); } }