Compare commits

...

2 Commits

Author SHA1 Message Date
4b2b9407e1 capacitor WIP 2024-12-12 08:20:34 +01:00
6bdd2ff20d Part.orientation in constructor 2024-12-12 08:19:51 +01:00
29 changed files with 327 additions and 108 deletions

View File

@ -77,7 +77,7 @@ public class CONFIG {
public static final BasicStroke SWITCH_STROKE = new BasicStroke(15); public static final BasicStroke SWITCH_STROKE = new BasicStroke(15);
public static boolean SHOW_WIRE_DETAILS = false; public static boolean SHOW_WIRE_DETAILS = true;
public static boolean SHOW_NODE_VOLTAGES = false; public static boolean SHOW_NODE_VOLTAGES = false;

View File

@ -2,13 +2,13 @@ package de.ph87.electro;
import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.CircuitPanel; import de.ph87.electro.circuit.CircuitPanel;
import de.ph87.electro.circuit.demo.Demos;
import de.ph87.electro.sidebar.Sidebar; import de.ph87.electro.sidebar.Sidebar;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import static de.ph87.electro.CONFIG.RASTER; import static de.ph87.electro.CONFIG.RASTER;
import static de.ph87.electro.circuit.demo.Demos.capacitor;
public class Window extends JFrame { public class Window extends JFrame {
@ -20,7 +20,7 @@ public class Window extends JFrame {
setPreferredSize(new Dimension(1200, 900)); setPreferredSize(new Dimension(1200, 900));
setExtendedState(MAXIMIZED_BOTH); setExtendedState(MAXIMIZED_BOTH);
final Sidebar sidebar = new Sidebar(() -> setCircuit(new Circuit())); final Sidebar sidebar = new Sidebar(() -> setCircuit(capacitor()));
final JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, sidebar, circuitPanel); final JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, sidebar, circuitPanel);
sidebar.setPreferredSize(new Dimension(calcWidth(3), 0)); sidebar.setPreferredSize(new Dimension(calcWidth(3), 0));
@ -38,7 +38,7 @@ public class Window extends JFrame {
public static void main(String[] args) { public static void main(String[] args) {
final Window window = new Window(); final Window window = new Window();
window.setCircuit(Demos.potiAndVoltmeter()); window.setCircuit(capacitor());
} }
public void setCircuit(final Circuit circuit) { public void setCircuit(final Circuit circuit) {

View File

@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j;
import java.awt.*; import java.awt.*;
import java.io.File; import java.io.File;
import java.time.Duration;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
@ -156,8 +157,17 @@ public class Circuit {
return new File(file.getAbsolutePath().replaceAll("\\.json$", ".png")); return new File(file.getAbsolutePath().replaceAll("\\.json$", ".png"));
} }
private long dtLast = 0;
public void evaluate() { public void evaluate() {
Calculation.calculate(this); final long now = System.nanoTime();
if (dtLast == 0) {
dtLast = now;
return;
}
final Duration dt = Duration.ofNanos(now - dtLast).dividedBy(10); // TODO remove /10
dtLast = now;
Calculation.calculate(this, dt);
} }
} }

View File

@ -28,6 +28,9 @@ public class CircuitPanel extends JPanel {
} }
}); });
final Thread thread = new Thread(this::run);
thread.setDaemon(true);
thread.start();
} }
public void setCircuit(@NonNull final Circuit circuit) { public void setCircuit(@NonNull final Circuit circuit) {
@ -44,4 +47,21 @@ public class CircuitPanel extends JPanel {
mouseAdapter.drawDrag(g); mouseAdapter.drawDrag(g);
} }
private void run() {
final Object lock = new Object();
while (true) {
circuit.evaluate();
repaint();
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (lock) {
try {
lock.wait(50);
} catch (InterruptedException e) {
log.error(e.toString());
return;
}
}
}
}
} }

View File

@ -1,5 +1,6 @@
package de.ph87.electro.circuit; package de.ph87.electro.circuit;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.parts.*; import de.ph87.electro.circuit.part.parts.*;
import de.ph87.electro.common.AbstractDropTarget; import de.ph87.electro.common.AbstractDropTarget;
@ -21,21 +22,21 @@ public class CircuitPanelDropTarget extends AbstractDropTarget {
protected boolean drop(final Point point, final String data) { protected boolean drop(final Point point, final String data) {
final Point aligned = ALIGN(point); final Point aligned = ALIGN(point);
if (data.equals(Battery.class.getSimpleName())) { if (data.equals(Battery.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Battery(aligned)); circuitPanel.getCircuit().addPart(new Battery(aligned, Orientation.R0));
} else if (data.equals(Light.class.getSimpleName())) { } else if (data.equals(Light.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Light(aligned)); circuitPanel.getCircuit().addPart(new Light(aligned, Orientation.R0));
} else if (data.equals(Switch1x1.class.getSimpleName())) { } else if (data.equals(Switch1x1.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Switch1x1(aligned)); circuitPanel.getCircuit().addPart(new Switch1x1(aligned, Orientation.R0));
} else if (data.equals(Switch1x2.class.getSimpleName())) { } else if (data.equals(Switch1x2.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Switch1x2(aligned)); circuitPanel.getCircuit().addPart(new Switch1x2(aligned, Orientation.R0));
} else if (data.equals(SwitchCross.class.getSimpleName())) { } else if (data.equals(SwitchCross.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new SwitchCross(aligned)); circuitPanel.getCircuit().addPart(new SwitchCross(aligned, Orientation.R0));
} else if (data.equals(Poti.class.getSimpleName())) { } else if (data.equals(Poti.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Poti(aligned)); circuitPanel.getCircuit().addPart(new Poti(aligned, Orientation.R0));
} else if (data.equals(Voltmeter.class.getSimpleName())) { } else if (data.equals(Voltmeter.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Voltmeter(aligned)); circuitPanel.getCircuit().addPart(new Voltmeter(aligned, Orientation.R0));
} else if (data.equals(Amperemeter.class.getSimpleName())) { } else if (data.equals(Amperemeter.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Amperemeter(aligned)); circuitPanel.getCircuit().addPart(new Amperemeter(aligned, Orientation.R0));
} else { } else {
throw new RuntimeException(); throw new RuntimeException();
} }

View File

@ -1,5 +1,6 @@
package de.ph87.electro.circuit; package de.ph87.electro.circuit;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import de.ph87.electro.circuit.part.parts.Connector; import de.ph87.electro.circuit.part.parts.Connector;
@ -191,7 +192,7 @@ class CircuitPanelMouseAdapter extends MouseAdapter {
} }
private void wireBendToNewConnector() { private void wireBendToNewConnector() {
final Connector newConnector = circuitPanel.getCircuit().addPart(new Connector(draggingSub)); final Connector newConnector = circuitPanel.getCircuit().addPart(new Connector(draggingSub, Orientation.R0));
connectIntermediate(newConnector.getNode()); connectIntermediate(newConnector.getNode());
} }

View File

@ -5,13 +5,15 @@ import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.Resistance; import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import de.ph87.electro.circuit.part.parts.Battery; import de.ph87.electro.circuit.part.parts.Capacitor;
import de.ph87.electro.circuit.part.parts.CurrentSource;
import de.ph87.electro.circuit.wire.Wire; import de.ph87.electro.circuit.wire.Wire;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.linear.*; import org.apache.commons.math3.linear.*;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -40,7 +42,7 @@ public class Calculation {
currents = new ArrayRealVector(numNodes); currents = new ArrayRealVector(numNodes);
} }
private Calculation(final Set<Node> connectedNodes, final Battery pivot) { private Calculation(@NonNull final Set<Node> connectedNodes, @NonNull final CurrentSource pivot, @NonNull final Duration dt) {
for (final Node node : connectedNodes) { for (final Node node : connectedNodes) {
if (node instanceof final Node partNode) { if (node instanceof final Node partNode) {
parts.add(partNode.getPart()); parts.add(partNode.getPart());
@ -56,19 +58,19 @@ public class Calculation {
currents = new ArrayRealVector(this.nodes.size()); currents = new ArrayRealVector(this.nodes.size());
fromSchematic(); fromSchematic();
solve(); solve();
toSchematic(); toSchematic(dt);
} }
public static List<Calculation> calculate(final Circuit circuit) { public static List<Calculation> calculate(@NonNull final Circuit circuit, @NonNull final Duration dt) {
final List<Calculation> calculations = new ArrayList<>(); final List<Calculation> calculations = new ArrayList<>();
final List<Battery> batteries = new ArrayList<>(circuit.streamParts().flatMap(Battery::filterCast).toList()); final List<CurrentSource> currentSources = new ArrayList<>(circuit.streamParts().flatMap(CurrentSource::filterCast).toList());
while (!batteries.isEmpty()) { while (!currentSources.isEmpty()) {
final Battery pivot = batteries.removeFirst(); final CurrentSource pivot = currentSources.removeFirst();
final Set<Node> connectedNodes = new HashSet<>(); final Set<Node> connectedNodes = new HashSet<>();
pivot.getPlus().collectConnectedNodes(connectedNodes); pivot.getPlus().collectConnectedNodes(connectedNodes);
pivot.getMinus().collectConnectedNodes(connectedNodes); pivot.getMinus().collectConnectedNodes(connectedNodes);
connectedNodes.stream().map(Node::getPart).flatMap(Battery::filterCast).forEach(batteries::remove); connectedNodes.stream().map(Node::getPart).flatMap(CurrentSource::filterCast).forEach(currentSources::remove);
calculations.add(new Calculation(connectedNodes, pivot)); calculations.add(new Calculation(connectedNodes, pivot, dt));
} }
return calculations; return calculations;
} }
@ -81,23 +83,25 @@ public class Calculation {
for (final Resistance resistance : part.getResistances()) { for (final Resistance resistance : part.getResistances()) {
addResistor(resistance.a, resistance.b, resistance.getResistance()); addResistor(resistance.a, resistance.b, resistance.getResistance());
} }
if (part instanceof final Battery battery) { if (part instanceof final CurrentSource currentSource) {
final double current = battery.getVoltage() / battery.getInnerResistance().getResistance(); if (!(currentSource instanceof final Capacitor capacitor) || !capacitor.isCharging()) {
final int indexMinus = getNodeIndex(battery.getMinus()); final double current = currentSource.getVoltage() / currentSource.getInnerResistance().getResistance();
final int indexPlus = getNodeIndex(battery.getPlus()); final int indexMinus = getNodeIndex(currentSource.getMinus());
addCurrentSource(indexMinus, indexPlus, current); final int indexPlus = getNodeIndex(currentSource.getPlus());
addCurrentSource(indexMinus, indexPlus, current);
}
} }
}); });
} }
private void toSchematic() { private void toSchematic(@NonNull final Duration dt) {
wires.forEach(wire -> wire.setCurrent(getCurrent(wire))); wires.forEach(wire -> wire.setCurrent(getCurrent(wire)));
parts.forEach(part -> { parts.forEach(part -> {
for (final Resistance resistance : part.getResistances()) { for (final Resistance resistance : part.getResistances()) {
resistance.setCurrent(getCurrent(resistance)); resistance.setCurrent(getCurrent(resistance));
} }
part.getNodes().forEach(node -> node.setVoltage(getPotential(node))); part.getNodes().forEach(node -> node.setVoltage(getPotential(node)));
part.postCalculate(); part.postCalculate(dt);
}); });
} }

View File

@ -1,20 +1,21 @@
package de.ph87.electro.circuit.demo; package de.ph87.electro.circuit.demo;
import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.part.parts.Battery; import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.parts.Poti; import de.ph87.electro.circuit.part.parts.*;
import de.ph87.electro.circuit.part.parts.Voltmeter; import lombok.NonNull;
import static de.ph87.electro.CONFIG.RASTER; import static de.ph87.electro.CONFIG.RASTER;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class Demos { public class Demos {
public static Circuit potiAndVoltmeter() { @NonNull
public static Circuit poti() {
final Circuit circuit = new Circuit(); final Circuit circuit = new Circuit();
final Battery battery = circuit.addPart(new Battery(RASTER(1, 0))); final Battery battery = circuit.addPart(new Battery(RASTER(1, 0), Orientation.R270));
final Poti poti = circuit.addPart(new Poti(RASTER(1, 2))); final Poti poti = circuit.addPart(new Poti(RASTER(1, 2), Orientation.R0));
final Voltmeter voltmeter = circuit.addPart(new Voltmeter(RASTER(1, 4))); final Voltmeter voltmeter = circuit.addPart(new Voltmeter(RASTER(1, 4), Orientation.R90));
circuit.connect(battery.getMinus(), poti.getCommon()); circuit.connect(battery.getMinus(), poti.getCommon());
circuit.connect(battery.getPlus(), poti.getEnd()); circuit.connect(battery.getPlus(), poti.getEnd());
circuit.connect(poti.getCommon(), voltmeter.a); circuit.connect(poti.getCommon(), voltmeter.a);
@ -22,4 +23,21 @@ public class Demos {
return circuit; return circuit;
} }
@NonNull
public static Circuit capacitor() {
final Circuit circuit = new Circuit();
final Capacitor capacitor = circuit.addPart(new Capacitor(RASTER(1, 0), Orientation.R0));
final Voltmeter voltmeter = circuit.addPart(new Voltmeter(RASTER(1, 2), Orientation.R0));
final Light light = circuit.addPart(new Light(RASTER(1, 4), Orientation.R0));
circuit.connect(capacitor.getMinus(), voltmeter.getA());
circuit.connect(voltmeter.getA(), light.getA());
circuit.connect(capacitor.getPlus(), voltmeter.getB());
circuit.connect(voltmeter.getB(), light.getB());
return circuit;
}
} }

View File

@ -12,6 +12,7 @@ import lombok.ToString;
import java.awt.*; import java.awt.*;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.*; import java.util.*;
@ -31,7 +32,7 @@ public abstract class Part {
private final List<Node> nodes = new ArrayList<>(); private final List<Node> nodes = new ArrayList<>();
@NonNull @NonNull
protected Orientation orientation = Orientation.R0; protected Orientation orientation;
@NonNull @NonNull
@Setter @Setter
@ -44,9 +45,10 @@ public abstract class Part {
@NonNull @NonNull
private AffineTransform transform = new AffineTransform(); private AffineTransform transform = new AffineTransform();
protected Part(@NonNull final String name, @NonNull final Point position) { protected Part(@NonNull final String name, @NonNull final Point position, @NonNull final Orientation orientation) {
this.uuid = UUID.randomUUID().toString(); this.uuid = UUID.randomUUID().toString();
this.name = name; this.name = name;
this.orientation = orientation;
this.position = position; this.position = position;
updateTransform(); updateTransform();
} }
@ -140,7 +142,7 @@ public abstract class Part {
// - // -
} }
public void postCalculate() { public void postCalculate(final @NonNull Duration dt) {
// - // -
} }

View File

@ -1,5 +1,6 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.part.Orientation;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
@ -8,8 +9,8 @@ import java.awt.*;
@Getter @Getter
public class Amperemeter extends Meter { public class Amperemeter extends Meter {
public Amperemeter(@NonNull final Point position) { public Amperemeter(@NonNull final Point position, @NonNull final Orientation orientation) {
super(MeterType.AMPERE, position); super(MeterType.AMPERE, position, orientation);
} }
public Amperemeter(@NonNull final MeterDto dto) { public Amperemeter(@NonNull final MeterDto dto) {

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Resistance; import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import lombok.Getter; import lombok.Getter;
@ -10,7 +11,6 @@ import lombok.ToString;
import java.awt.*; import java.awt.*;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
import static de.ph87.electro.CONFIG.*; import static de.ph87.electro.CONFIG.*;
import static de.ph87.electro.circuit.CircuitPainter.*; import static de.ph87.electro.circuit.CircuitPainter.*;
@ -18,7 +18,7 @@ import static java.lang.Math.round;
@Getter @Getter
@ToString(callSuper = true, onlyExplicitlyIncluded = true) @ToString(callSuper = true, onlyExplicitlyIncluded = true)
public class Battery extends Part { public class Battery extends Part implements CurrentSource {
public static final double DEFAULT_INNER_RESISTANCE = 0.05; public static final double DEFAULT_INNER_RESISTANCE = 0.05;
@ -49,8 +49,8 @@ public class Battery extends Part {
@ToString.Include @ToString.Include
private double voltage = DEFAULT_VOLTAGE; private double voltage = DEFAULT_VOLTAGE;
public Battery(@NonNull final Point position) { public Battery(@NonNull final Point position, @NonNull final Orientation orientation) {
super("Batterie", position); super("Batterie", position, orientation);
minus = addNode("MINUS", P10, P50); minus = addNode("MINUS", P10, P50);
plus = addNode("PLUS", P90, P50); plus = addNode("PLUS", P90, P50);
innerResistance = new Resistance(minus, plus, DEFAULT_INNER_RESISTANCE); innerResistance = new Resistance(minus, plus, DEFAULT_INNER_RESISTANCE);
@ -64,14 +64,6 @@ public class Battery extends Part {
innerResistance = new Resistance(minus, plus, dto.getResistance()); innerResistance = new Resistance(minus, plus, dto.getResistance());
} }
@NonNull
public static Stream<Battery> filterCast(@NonNull final Part part) {
if (part instanceof final Battery battery) {
return Stream.of(battery);
}
return Stream.empty();
}
@Override @Override
protected void _render(@NonNull final Graphics2D g) { protected void _render(@NonNull final Graphics2D g) {
drawLine(g, P10, P50, P50 - GAP / 2 - MINUS_W / 2, P50, Color.BLACK, SYMBOL_STROKE); drawLine(g, P10, P50, P50 - GAP / 2 - MINUS_W / 2, P50, Color.BLACK, SYMBOL_STROKE);

View File

@ -0,0 +1,119 @@
package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import java.awt.*;
import java.time.Duration;
import java.util.List;
import static de.ph87.electro.CONFIG.*;
import static de.ph87.electro.circuit.CircuitPainter.*;
import static java.lang.Math.round;
@Getter
@ToString(callSuper = true)
public class Capacitor extends Part implements CurrentSource {
private static final int MINUS_W = (int) round(0.1 * RASTER);
private static final int GAP = (int) round(0.05 * RASTER);
private static final int PLUS_W = (int) round(0.02 * RASTER);
private static final int PLUS_H = (int) round(0.6 * RASTER);
private final Point size = new Point(RASTER, RASTER);
private final Node plus;
private final Node minus;
private final Resistance innerResistance;
private double capacityFarad = 1;
private double chargeCoulomb = capacityFarad * 3;
private double innerVoltage = chargeCoulomb / capacityFarad;
private double outerVoltage;
private boolean charging = false;
public Capacitor(@NonNull final Point position, @NonNull final Orientation orientation) {
super("Kondensator", position, orientation);
minus = addNode("-", P10, P50);
plus = addNode("+", P90, P50);
innerResistance = new Resistance(plus, minus, RESISTANCE_MAX);
}
public Capacitor(@NonNull final LightDto dto) {
super(dto);
minus = addNode(dto.getB(), P10, P50);
plus = addNode(dto.getA(), P90, P50);
capacityFarad = 0;
innerResistance = new Resistance(plus, minus, dto.getResistance());
}
@Override
public void postCalculate(@NonNull final Duration dt) {
outerVoltage = plus.getVoltage() - minus.getVoltage();
final double timeSeconds = dt.toNanos() / 1_000_000_000.0;
final double current = innerResistance.getCurrent();
if (!Double.isNaN(outerVoltage) && innerVoltage < outerVoltage) {
innerResistance.setResistance(RESISTANCE_MIN);
final double resistance = outerVoltage / current;
final double targetCharge = capacityFarad * outerVoltage;
final double deltaCharge = (targetCharge - chargeCoulomb) * (timeSeconds / (timeSeconds + RC(resistance)));
chargeCoulomb += deltaCharge;
} else {
innerResistance.setResistance(RESISTANCE_MAX);
chargeCoulomb += current * timeSeconds;
if (chargeCoulomb < 0) {
chargeCoulomb = 0;
}
}
innerVoltage = chargeCoulomb / capacityFarad;
charging = !Double.isNaN(outerVoltage) && innerVoltage < outerVoltage;
}
public double getVoltage() {
if (!Double.isNaN(plus.getVoltage()) && !Double.isNaN(minus.getVoltage())) {
if (innerVoltage < outerVoltage) {
return outerVoltage;
}
}
return innerVoltage;
}
private double RC(final double resistance) {
return resistance * capacityFarad;
}
@Override
protected void _render(@NonNull final Graphics2D g) {
drawLine(g, P10, P50, P50 - GAP / 2 - MINUS_W / 2, P50, Color.BLACK, SYMBOL_STROKE);
drawLine(g, P50 + GAP / 2 + PLUS_W / 2, P50, P90, P50, Color.BLACK, SYMBOL_STROKE);
fillRect(g, P50 - MINUS_W - GAP / 2, P50 - PLUS_H / 2, MINUS_W, PLUS_H, Color.BLACK);
fillRect(g, P50 + GAP / 2, P50 - PLUS_H / 2, MINUS_W, PLUS_H, Color.BLACK);
}
@Override
protected void _labels(@NonNull final Graphics2D g) {
drawText(g, LABEL_FONT, "%.1fC %.1fV".formatted(chargeCoulomb, getVoltage()), P50, P10, Color.BLACK, orientation);
}
@NonNull
@Override
public java.util.List<Resistance> getResistances() {
return List.of(innerResistance);
}
}

View File

@ -1,5 +1,6 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import lombok.Getter; import lombok.Getter;
@ -20,8 +21,8 @@ public class Connector extends Part {
@NonNull @NonNull
private final Point size = new Point(SUB_RASTER, SUB_RASTER); private final Point size = new Point(SUB_RASTER, SUB_RASTER);
public Connector(@NonNull final Point position) { public Connector(@NonNull final Point position, @NonNull final Orientation orientation) {
super("", position); super("", position, orientation);
node = addNode("", SUB_RASTER / 2, SUB_RASTER / 2); node = addNode("", SUB_RASTER / 2, SUB_RASTER / 2);
} }

View File

@ -0,0 +1,28 @@
package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node;
import lombok.NonNull;
import java.util.stream.Stream;
public interface CurrentSource {
Node getPlus();
Node getMinus();
double getVoltage();
Resistance getInnerResistance();
@NonNull
static Stream<CurrentSource> filterCast(@NonNull final Part part) {
if (part instanceof final CurrentSource currentSource) {
return Stream.of(currentSource);
}
return Stream.empty();
}
}

View File

@ -9,6 +9,7 @@ import lombok.NonNull;
import lombok.ToString; import lombok.ToString;
import java.awt.*; import java.awt.*;
import java.time.Duration;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -43,8 +44,8 @@ public class Light extends Part {
private Color color = BULB_OFF_COLOR; private Color color = BULB_OFF_COLOR;
public Light(@NonNull final Point position) { public Light(@NonNull final Point position, @NonNull final Orientation orientation) {
super("Licht", position); super("Licht", position, orientation);
a = addNode("A", P10, P50); a = addNode("A", P10, P50);
b = addNode("B", P90, P50); b = addNode("B", P90, P50);
innerResistance = new Resistance(a, b, DEFAULT_INNER_RESISTANCE); innerResistance = new Resistance(a, b, DEFAULT_INNER_RESISTANCE);
@ -65,7 +66,7 @@ public class Light extends Part {
} }
@Override @Override
public void postCalculate() { public void postCalculate(@NonNull final Duration dt) {
potentialDifference = abs(b.getVoltage() - a.getVoltage()); potentialDifference = abs(b.getVoltage() - a.getVoltage());
defect |= potentialDifference > maxVoltage; defect |= potentialDifference > maxVoltage;
if (defect) { if (defect) {

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Resistance; import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import de.ph87.electro.common.RotationMatrix; import de.ph87.electro.common.RotationMatrix;
@ -17,6 +18,7 @@ import static de.ph87.electro.CONFIG.*;
import static de.ph87.electro.circuit.CircuitPainter.*; import static de.ph87.electro.circuit.CircuitPainter.*;
import static java.lang.Math.round; import static java.lang.Math.round;
@Getter
public abstract class Meter extends Part { public abstract class Meter extends Part {
private static final int FINGER_LENGTH = P65; private static final int FINGER_LENGTH = P65;
@ -31,7 +33,6 @@ public abstract class Meter extends Part {
public final MeterType type; public final MeterType type;
@Getter
public final Point size = new Point(RASTER, RASTER); public final Point size = new Point(RASTER, RASTER);
public final Node a; public final Node a;
@ -48,8 +49,8 @@ public abstract class Meter extends Part {
@Setter @Setter
public double max; public double max;
public Meter(@NonNull MeterType type, @NonNull final Point position) { public Meter(@NonNull MeterType type, @NonNull final Point position, @NonNull final Orientation orientation) {
super(type.name, position); super(type.name, position, orientation);
this.type = type; this.type = type;
this.unit = type.unit; this.unit = type.unit;
this.min = type.min; this.min = type.min;

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Resistance; import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import lombok.Getter; import lombok.Getter;
@ -39,8 +40,8 @@ public class Poti extends Part {
private double ratio = 0.0; private double ratio = 0.0;
public Poti(@NonNull final Point position) { public Poti(@NonNull final Point position, @NonNull final Orientation orientation) {
super("Poti", position); super("Poti", position, orientation);
common = addNode("C", P10, P50); common = addNode("C", P10, P50);
middle = addNode("M", P50, P10); middle = addNode("M", P50, P10);
end = addNode("E", P90, P50); end = addNode("E", P90, P50);

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Resistance; import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import lombok.Getter; import lombok.Getter;
@ -26,15 +27,18 @@ public class Switch1x1 extends Part {
private final Node output; private final Node output;
private final Resistance innerResistance; private final Resistance resistanceOpen;
private final Resistance resistanceClosed;
private boolean state = false; private boolean state = false;
public Switch1x1(@NonNull final Point position) { public Switch1x1(@NonNull final Point position, @NonNull final Orientation orientation) {
super("Ausschalter", position); super("Ausschalter", position, orientation);
common = addNode("C", P10, P50); common = addNode("C", P10, P50);
output = addNode("O", P90, P50); output = addNode("O", P90, P50);
innerResistance = new Resistance(common, output, RESISTANCE_MIN); resistanceOpen = new Resistance(common, output, RESISTANCE_MAX);
resistanceClosed = new Resistance(common, output, RESISTANCE_MIN);
} }
public Switch1x1(@NonNull final Switch1x1Dto dto) { public Switch1x1(@NonNull final Switch1x1Dto dto) {
@ -42,7 +46,8 @@ public class Switch1x1 extends Part {
common = addNode(dto.getCommon(), P10, P50); common = addNode(dto.getCommon(), P10, P50);
output = addNode(dto.getOutput(), P90, P50); output = addNode(dto.getOutput(), P90, P50);
state = dto.isState(); state = dto.isState();
innerResistance = new Resistance(common, output, RESISTANCE_MIN); resistanceOpen = new Resistance(common, output, RESISTANCE_MAX);
resistanceClosed = new Resistance(common, output, RESISTANCE_MIN);
} }
public void setState(@NonNull final boolean state) { public void setState(@NonNull final boolean state) {
@ -67,8 +72,9 @@ public class Switch1x1 extends Part {
@Override @Override
public List<Resistance> getResistances() { public List<Resistance> getResistances() {
if (state) { if (state) {
return List.of(innerResistance); return List.of(resistanceClosed);
} }
// return List.of(resistanceOpen);
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Resistance; import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import lombok.Getter; import lombok.Getter;
@ -31,8 +32,8 @@ public class Switch1x2 extends Part {
private boolean state = false; private boolean state = false;
public Switch1x2(@NonNull final Point position) { public Switch1x2(@NonNull final Point position, @NonNull final Orientation orientation) {
super("Wechselschalter", position); super("Wechselschalter", position, orientation);
common = addNode("C", P10, P50); common = addNode("C", P10, P50);
output0 = addNode("O0", P90, P25); output0 = addNode("O0", P90, P25);
output1 = addNode("O1", P90, P75); output1 = addNode("O1", P90, P75);

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Resistance; import de.ph87.electro.circuit.Resistance;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import lombok.Getter; import lombok.Getter;
@ -37,8 +38,8 @@ public class SwitchCross extends Part {
private boolean state = false; private boolean state = false;
public SwitchCross(final Point position) { public SwitchCross(@NonNull final Point position, @NonNull final Orientation orientation) {
super("Kreuzschalter", position); super("Kreuzschalter", position, orientation);
common0 = addNode("C0", P10, P25); common0 = addNode("C0", P10, P25);
common1 = addNode("C1", P10, P75); common1 = addNode("C1", P10, P75);
output0 = addNode("O0", P90, P25); output0 = addNode("O0", P90, P25);

View File

@ -1,5 +1,6 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.part.Orientation;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
@ -8,8 +9,8 @@ import java.awt.*;
@Getter @Getter
public class Voltmeter extends Meter { public class Voltmeter extends Meter {
public Voltmeter(@NonNull final Point position) { public Voltmeter(@NonNull final Point position, @NonNull final Orientation orientation) {
super(MeterType.VOLT, position); super(MeterType.VOLT, position, orientation);
} }
public Voltmeter(@NonNull final MeterDto dto) { public Voltmeter(@NonNull final MeterDto dto) {

View File

@ -1,5 +1,6 @@
package de.ph87.electro.sidebar; package de.ph87.electro.sidebar;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.parts.*; import de.ph87.electro.circuit.part.parts.*;
@ -22,14 +23,14 @@ public class Sidebar extends JPanel {
addToggle("Spannungen", () -> SHOW_NODE_VOLTAGES, v -> SHOW_NODE_VOLTAGES = v); addToggle("Spannungen", () -> SHOW_NODE_VOLTAGES, v -> SHOW_NODE_VOLTAGES = v);
final Point ZERO = new Point(); final Point ZERO = new Point();
addPart(new Battery(ZERO)); addPart(new Battery(ZERO, Orientation.R0));
addPart(new Light(ZERO)); addPart(new Light(ZERO, Orientation.R0));
addPart(new Switch1x1(ZERO)); addPart(new Switch1x1(ZERO, Orientation.R0));
addPart(new Switch1x2(ZERO)); addPart(new Switch1x2(ZERO, Orientation.R0));
addPart(new SwitchCross(ZERO)); addPart(new SwitchCross(ZERO, Orientation.R0));
addPart(new Poti(ZERO)); addPart(new Poti(ZERO, Orientation.R0));
addPart(new Voltmeter(ZERO)); addPart(new Voltmeter(ZERO, Orientation.R0));
addPart(new Amperemeter(ZERO)); addPart(new Amperemeter(ZERO, Orientation.R0));
} }
@SuppressWarnings("UnusedReturnValue") @SuppressWarnings("UnusedReturnValue")

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit; package de.ph87.electro.circuit;
import de.ph87.electro.circuit.calculation.Calculation; import de.ph87.electro.circuit.calculation.Calculation;
import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.node.Node;
import de.ph87.electro.circuit.part.parts.Battery; import de.ph87.electro.circuit.part.parts.Battery;
import de.ph87.electro.circuit.part.parts.Light; import de.ph87.electro.circuit.part.parts.Light;
@ -8,6 +9,8 @@ import de.ph87.electro.circuit.wire.Wire;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.time.Duration;
import static de.ph87.electro.CONFIG.RASTER; import static de.ph87.electro.CONFIG.RASTER;
@Slf4j @Slf4j
@ -16,12 +19,12 @@ class CalculationServiceTest {
@Test @Test
void test() { void test() {
final Circuit circuit = new Circuit(); final Circuit circuit = new Circuit();
final Battery battery = circuit.addPart(new Battery(RASTER(0, 0))); final Battery battery = circuit.addPart(new Battery(RASTER(0, 0), Orientation.R0));
final Light light = circuit.addPart(new Light(RASTER(0, 1))); final Light light = circuit.addPart(new Light(RASTER(0, 1), Orientation.R0));
circuit.connect(battery.getMinus(), light.getA()); circuit.connect(battery.getMinus(), light.getA());
circuit.connect(battery.getPlus(), light.getB()); circuit.connect(battery.getPlus(), light.getB());
for (final Calculation calculation : Calculation.calculate(circuit)) { for (final Calculation calculation : Calculation.calculate(circuit, Duration.ofNanos(1))) {
calculation.toString().lines().forEach(log::info); calculation.toString().lines().forEach(log::info);
circuit.streamParts().forEach(part -> { circuit.streamParts().forEach(part -> {
log.info(""); log.info("");

View File

@ -2,8 +2,9 @@ package de.ph87.electro.circuit.io;
import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.CircuitIOService; import de.ph87.electro.circuit.CircuitIOService;
import de.ph87.electro.circuit.part.node.Node; import de.ph87.electro.circuit.part.Orientation;
import de.ph87.electro.circuit.part.Part; import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.node.Node;
import de.ph87.electro.circuit.part.parts.Battery; import de.ph87.electro.circuit.part.parts.Battery;
import de.ph87.electro.circuit.part.parts.Light; import de.ph87.electro.circuit.part.parts.Light;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -23,8 +24,8 @@ class CircuitIOServiceTest {
@Test @Test
void serialization() throws IOException { void serialization() throws IOException {
final Circuit circuit = new Circuit(); final Circuit circuit = new Circuit();
final Battery battery = circuit.addPart(new Battery(RASTER(0, 0))); final Battery battery = circuit.addPart(new Battery(RASTER(0, 0), Orientation.R0));
final Light light = circuit.addPart(new Light(RASTER(0, 1))); final Light light = circuit.addPart(new Light(RASTER(0, 1), Orientation.R0));
circuit.connect(battery.getPlus(), light.getB()); circuit.connect(battery.getPlus(), light.getB());
circuit.connect(light.getA(), battery.getMinus()); circuit.connect(light.getA(), battery.getMinus());
check(circuit); check(circuit);

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.part.Orientation;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -14,9 +15,9 @@ public class BatteryLightTest {
private static final Circuit CIRCUIT = new Circuit(); private static final Circuit CIRCUIT = new Circuit();
private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0))); private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0), Orientation.R0));
private static final Light light = CIRCUIT.addPart(new Light(RASTER(0, 1))); private static final Light light = CIRCUIT.addPart(new Light(RASTER(0, 1), Orientation.R0));
@BeforeAll @BeforeAll
public static void setUp() { public static void setUp() {

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.part.Orientation;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -15,11 +16,11 @@ public class BatterySwitcher1x1Test {
private static final Circuit CIRCUIT = new Circuit(); private static final Circuit CIRCUIT = new Circuit();
private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0))); private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0), Orientation.R0));
private static final Switch1x1 switcher = CIRCUIT.addPart(new Switch1x1(RASTER(0, 1))); private static final Switch1x1 switcher = CIRCUIT.addPart(new Switch1x1(RASTER(0, 1), Orientation.R0));
private static final Light light = CIRCUIT.addPart(new Light(RASTER(1, 0))); private static final Light light = CIRCUIT.addPart(new Light(RASTER(1, 0), Orientation.R0));
@BeforeAll @BeforeAll
public static void setUp() { public static void setUp() {

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.part.Orientation;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -15,13 +16,13 @@ public class BatterySwitcher1x2Test {
private static final Circuit CIRCUIT = new Circuit(); private static final Circuit CIRCUIT = new Circuit();
private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0))); private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0), Orientation.R0));
private static final Switch1x2 switcher = CIRCUIT.addPart(new Switch1x2(RASTER(0, 2))); private static final Switch1x2 switcher = CIRCUIT.addPart(new Switch1x2(RASTER(0, 2), Orientation.R0));
private static final Light light0 = CIRCUIT.addPart(new Light(RASTER(1, 1))); private static final Light light0 = CIRCUIT.addPart(new Light(RASTER(1, 1), Orientation.R0));
private static final Light light1 = CIRCUIT.addPart(new Light(RASTER(1, 3))); private static final Light light1 = CIRCUIT.addPart(new Light(RASTER(1, 3), Orientation.R0));
@BeforeAll @BeforeAll
public static void setUp() { public static void setUp() {

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.part.Orientation;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -15,13 +16,13 @@ public class BatterySwitcher2x2Test {
private static final Circuit CIRCUIT = new Circuit(); private static final Circuit CIRCUIT = new Circuit();
private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0))); private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0), Orientation.R0));
private static final Switch1x2 switcher0 = CIRCUIT.addPart(new Switch1x2(RASTER(0, 1))); private static final Switch1x2 switcher0 = CIRCUIT.addPart(new Switch1x2(RASTER(0, 1), Orientation.R0));
private static final Switch1x2 switcher1 = CIRCUIT.addPart(new Switch1x2(RASTER(1, 1))); private static final Switch1x2 switcher1 = CIRCUIT.addPart(new Switch1x2(RASTER(1, 1), Orientation.R0));
private static final Light light = CIRCUIT.addPart(new Light(RASTER(1, 0))); private static final Light light = CIRCUIT.addPart(new Light(RASTER(1, 0), Orientation.R0));
@BeforeAll @BeforeAll
public static void setUp() { public static void setUp() {

View File

@ -1,6 +1,7 @@
package de.ph87.electro.circuit.part.parts; package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Circuit; import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.part.Orientation;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -15,15 +16,15 @@ public class BatterySwitcherCrossTest {
private static final Circuit CIRCUIT = new Circuit(); private static final Circuit CIRCUIT = new Circuit();
private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0))); private static final Battery battery = CIRCUIT.addPart(new Battery(RASTER(0, 0), Orientation.R0));
private static final Switch1x2 switcher0 = CIRCUIT.addPart(new Switch1x2(RASTER(0, 1))); private static final Switch1x2 switcher0 = CIRCUIT.addPart(new Switch1x2(RASTER(0, 1), Orientation.R0));
private static final SwitchCross switcherX = CIRCUIT.addPart(new SwitchCross(RASTER(1, 1))); private static final SwitchCross switcherX = CIRCUIT.addPart(new SwitchCross(RASTER(1, 1), Orientation.R0));
private static final Switch1x2 switcher1 = CIRCUIT.addPart(new Switch1x2(RASTER(2, 1))); private static final Switch1x2 switcher1 = CIRCUIT.addPart(new Switch1x2(RASTER(2, 1), Orientation.R0));
private static final Light light = CIRCUIT.addPart(new Light(RASTER(2, 0))); private static final Light light = CIRCUIT.addPart(new Light(RASTER(2, 0), Orientation.R0));
@BeforeAll @BeforeAll
public static void setUp() { public static void setUp() {