package de.ph87.electro.circuit.wire; import de.ph87.electro.circuit.part.node.Node; import lombok.Getter; import lombok.NonNull; import lombok.Setter; import lombok.ToString; import java.awt.*; import java.awt.geom.Rectangle2D; import static de.ph87.electro.CONFIG.*; import static java.lang.Math.*; @Getter @ToString public class Wire { @NonNull private final Node a; @NonNull private final Node b; @Setter private double current = Double.NaN; @Setter private boolean ghost = false; public Wire(@NonNull final Node a, @NonNull final Node b) { this.a = a; this.b = b; a.getWires().add(this); b.getWires().add(this); } public boolean intersects(final Point position) { return distanceToLine(position, a.getPosition(), b.getPosition()); } public boolean distanceToLine(final Point point, final Point lineStart, final Point lineEnd) { double dx = lineEnd.x - lineStart.x; double dy = lineEnd.y - lineStart.y; double lineLength = dx * dx + dy * dy; if (lineLength == 0) { return sqrt(pow(lineStart.x - point.x, 2) + pow(lineStart.y - point.y, 2)) <= WIRE_HOVER_STROKE_BACK.getLineWidth(); } double t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / lineLength; t = Math.max(0, Math.min(1, t)); double closestX = lineStart.x + t * dx; double closestY = lineStart.y + t * dy; final double distance = sqrt(pow(closestX - point.x, 2) + pow(closestY - point.y, 2)); return distance <= WIRE_HOVER_STROKE_BACK.getLineWidth(); } public Node getOpposite(final Node node) { if (a == node) { return b; } else if (b == node) { return a; } throw new RuntimeException(); } public double getCurrent(final Node node) { return node == a ? current : -current; } public void draw(final Graphics2D g) { final Color color = ghost ? new Color(a.getColor().getRed(), a.getColor().getGreen(), a.getColor().getBlue(), 64) : a.getColor(); g.setColor(color); g.setStroke(WIRE_STROKE); g.drawLine(a.getPosition().x, a.getPosition().y, b.getPosition().x, b.getPosition().y); if (SHOW_WIRE_DETAILS) { drawValues(g, "%.2f A".formatted(abs(current)), -0.5); drawValues(g, "%.2f V".formatted(a.getVoltage()), +0.5); } } private void drawValues(final Graphics2D g, final String string, final double offset) { g.setFont(LABEL_FONT); final Rectangle2D bounds = g.getFontMetrics().getStringBounds(string, g); final Point aa = a.getPosition(); final Point bb = b.getPosition(); final int mx = (aa.x + bb.x) / 2; final int my = (aa.y + bb.y) / 2; final int bx = (int) round((mx - bounds.getWidth() / 2)) - 2; final int by = (int) round((my - bounds.getHeight() / 2) + offset * bounds.getHeight()) - 2; g.setColor(new Color(255, 255, 255, 200)); g.fillRect(bx, by, (int) round(bounds.getWidth()) + 4, (int) round(bounds.getHeight()) + 4); final int sx = (int) round((mx - bounds.getWidth() / 2)); final int sy = (int) round(my + bounds.getHeight() / 3 + offset * bounds.getHeight()); g.setColor(a.getColor()); g.drawString(string, sx, sy); } }