Voltmeter

This commit is contained in:
Patrick Haßel 2024-05-23 15:20:42 +02:00
parent e71791d0b2
commit 02a24b43e7
16 changed files with 182 additions and 16 deletions

View File

@ -6,6 +6,10 @@ import static java.lang.Math.round;
public class CONFIG {
public static final double NO_RESISTANCE = 1e-12;
public static final double MAX_RESISTANCE = 1 / NO_RESISTANCE;
public static boolean SHOW_WIRE_DETAILS = true;
public static boolean SHOW_JUNCTION_VOLTAGES = false;

View File

@ -5,6 +5,9 @@ import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.PartDto;
import de.ph87.electro.circuit.part.Position;
import de.ph87.electro.circuit.part.junction.Junction;
import de.ph87.electro.circuit.part.parts.Battery;
import de.ph87.electro.circuit.part.parts.Poti;
import de.ph87.electro.circuit.part.parts.Voltmeter;
import de.ph87.electro.circuit.wire.Wire;
import de.ph87.electro.circuit.wire.WireDto;
import lombok.Getter;
@ -19,6 +22,8 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import static de.ph87.electro.circuit.part.Position.RST;
public class Circuit {
@Getter
@ -40,7 +45,7 @@ public class Circuit {
public Circuit(final File file, final CircuitDto dto) {
created = dto.getCreated();
for (PartDto partDto : dto.getParts()) {
final Part part = Part.of(this, partDto);
final Part part = Part.fromDto(this, partDto);
verifyFree(part.getPosition());
parts.add(part);
}

View File

@ -37,6 +37,8 @@ public class CircuitPanelDropTarget extends AbstractDropTarget {
circuitPanel.getCircuit().addPart(new SwitchCross(circuitPanel.getCircuit(), position));
} else if (data.equals(Poti.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Poti(circuitPanel.getCircuit(), position));
} else if (data.equals(Voltmeter.class.getSimpleName())) {
circuitPanel.getCircuit().addPart(new Voltmeter(circuitPanel.getCircuit(), position));
} else {
throw new RuntimeException();
}

View File

@ -1,5 +1,6 @@
package de.ph87.electro.circuit.calculation;
import de.ph87.electro.CONFIG;
import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.part.InnerConnection;
import de.ph87.electro.circuit.part.Part;
@ -22,10 +23,6 @@ import static java.lang.Math.max;
@Getter
public class Calculation {
public static final double NO_RESISTANCE = 1e-12;
private static final double FULL_ADMITTANCE = 1 / NO_RESISTANCE;
private final List<Junction> junctions = new ArrayList<>();
private final Set<Part> parts = new HashSet<>();
@ -76,7 +73,7 @@ public class Calculation {
private void fromSchematic() {
wires.forEach(
wire -> addResistor(wire.getA(), wire.getB(), NO_RESISTANCE)
wire -> addResistor(wire.getA(), wire.getB(), CONFIG.NO_RESISTANCE)
);
parts.forEach(part -> {
for (final InnerConnection innerConnection : part.getInnerConnections()) {
@ -113,7 +110,7 @@ public class Calculation {
private double getCurrent(final Wire wire) {
final int indexA = getJunctionIndex(wire.getA());
final int indexB = getJunctionIndex(wire.getB());
final double conductance = indexA >= 0 && indexB >= 0 ? matrix.getEntry(indexA, indexB) : FULL_ADMITTANCE;
final double conductance = indexA >= 0 && indexB >= 0 ? matrix.getEntry(indexA, indexB) : 1 / CONFIG.NO_RESISTANCE;
final double potentialDifference = getPotential(wire.getB()) - getPotential(wire.getA());
return conductance * potentialDifference;
}

View File

@ -80,7 +80,7 @@ public abstract class Part {
evaluate();
}
public void render() {
public final void render() {
render.rect(ZERO, RASTER, RASTER, null, null, PART_BACKGROUND);
_labels();
@ -136,7 +136,7 @@ public abstract class Part {
return Collections.emptyList();
}
public static Part of(final Circuit circuit, final PartDto abstractDto) {
public static Part fromDto(final Circuit circuit, final PartDto abstractDto) {
return switch (abstractDto) {
case final BatteryDto dto -> new Battery(circuit, dto);
case final ConnectorCornerDto dto -> new ConnectorCorner(circuit, dto);
@ -146,6 +146,8 @@ public abstract class Part {
case final Switch1x1Dto dto -> new Switch1x1(circuit, dto);
case final Switch1x2Dto dto -> new Switch1x2(circuit, dto);
case final SwitchCrossDto dto -> new SwitchCross(circuit, dto);
case final PotiDto dto -> new Poti(circuit, dto);
case final VoltmeterDto dto -> new Voltmeter(circuit, dto);
case null, default -> throw new RuntimeException();
};
}

View File

@ -40,6 +40,7 @@ public abstract class PartDto {
case final Switch1x2 part -> new Switch1x2Dto(part);
case final SwitchCross part -> new SwitchCrossDto(part);
case final Poti part -> new PotiDto(part);
case final Voltmeter part -> new VoltmeterDto(part);
case null, default -> throw new RuntimeException();
};
}

View File

@ -2,6 +2,7 @@ package de.ph87.electro.circuit.part;
import lombok.Getter;
import lombok.ToString;
import org.apache.commons.math3.linear.RealVector;
import java.awt.*;
import java.awt.event.MouseEvent;
@ -22,6 +23,10 @@ public final class Position {
public final Point raster;
public static Position ABS(final RealVector vector) {
return ABS(vector.getEntry(0), vector.getEntry(1));
}
public static Position ABS(final double absoluteX, final double absoluteY) {
return new Position((int) round(absoluteX), (int) round(absoluteY));
}

View File

@ -19,11 +19,11 @@ public class Render {
private final Graphics2D g = image.createGraphics();
public void line(final Junction junction0, final Junction junction1, final Color color, final BasicStroke stroke) {
public void line(final Junction junction0, final Junction junction1, final Color color, final Stroke stroke) {
line(junction0.getPosition(), junction1.getPosition(), color, stroke);
}
public void line(final Position p0, final Position p1, final Color color, final BasicStroke stroke) {
public void line(final Position p0, final Position p1, final Color color, final Stroke stroke) {
if (color != null) {
g.setColor(color);
}

View File

@ -13,7 +13,6 @@ import java.awt.*;
import java.util.List;
import static de.ph87.electro.CONFIG.*;
import static de.ph87.electro.circuit.calculation.Calculation.NO_RESISTANCE;
import static java.lang.Math.max;
@Getter
@ -38,7 +37,7 @@ public class Poti extends Part {
end = addJunction("E", P90, P50);
}
protected Poti(final Circuit circuit, final PotiDto dto) {
public Poti(final Circuit circuit, final PotiDto dto) {
super(circuit, dto);
common = addJunction(dto.getCommon().getName(), P10, P50);
middle = addJunction(dto.getMiddle().getName(), P50, P10);

View File

@ -0,0 +1,23 @@
package de.ph87.electro.circuit.part.parts;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.RealMatrix;
import static java.lang.Math.cos;
import static java.lang.Math.sin;
public class RotationMatrix extends Array2DRowRealMatrix {
public static RealMatrix ofDegrees(final double degrees) {
final double radians = degrees * Math.PI / 180.0;
return new RotationMatrix(radians);
}
private RotationMatrix(final double radians) {
super(new double[][]{
{cos(radians), -sin(radians)},
{sin(radians), cos(radians)},
});
}
}

View File

@ -12,7 +12,7 @@ import java.awt.*;
import java.util.List;
import static de.ph87.electro.CONFIG.*;
import static de.ph87.electro.circuit.calculation.Calculation.NO_RESISTANCE;
import static de.ph87.electro.CONFIG.NO_RESISTANCE;
@Getter
@ToString(callSuper = true)

View File

@ -11,7 +11,7 @@ import lombok.ToString;
import java.util.List;
import static de.ph87.electro.CONFIG.*;
import static de.ph87.electro.circuit.calculation.Calculation.NO_RESISTANCE;
import static de.ph87.electro.CONFIG.NO_RESISTANCE;
@Getter
@ToString(callSuper = true)

View File

@ -11,7 +11,7 @@ import lombok.ToString;
import java.util.List;
import static de.ph87.electro.CONFIG.*;
import static de.ph87.electro.circuit.calculation.Calculation.NO_RESISTANCE;
import static de.ph87.electro.CONFIG.NO_RESISTANCE;
@Getter
@ToString(callSuper = true)

View File

@ -0,0 +1,95 @@
package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.Circuit;
import de.ph87.electro.circuit.part.InnerConnection;
import de.ph87.electro.circuit.part.Part;
import de.ph87.electro.circuit.part.PartDto;
import de.ph87.electro.circuit.part.Position;
import de.ph87.electro.circuit.part.junction.Junction;
import lombok.Getter;
import org.apache.commons.math3.linear.ArrayRealVector;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.RealVector;
import java.awt.*;
import java.util.List;
import static de.ph87.electro.CONFIG.*;
import static de.ph87.electro.circuit.part.Position.ABS;
@Getter
public class Voltmeter extends Part {
private static final RealVector ANCHOR = new ArrayRealVector(new double[]{P50, P50});
private static final RealVector FINGER = new ArrayRealVector(new double[]{P90, P50}).subtract(ANCHOR);
private static final Stroke SCALE_STROKE = new BasicStroke(1);
private static final double DEGREES_TOTAL = 90.0;
private static final double DEGREES_ROTATE = -135.0;
private final Junction a;
private final Junction b;
private double min = -3;
private double max = +3;
private double voltage;
private RealVector tip;
public Voltmeter(final Circuit circuit, final Position position) {
super(circuit, "Voltmeter", position);
a = addJunction("A", P10, P50);
b = addJunction("B", P90, P50);
postCalculate(); // TODO remove
}
public Voltmeter(final Circuit circuit, final PartDto dto) {
super(circuit, dto);
a = addJunction("A", P10, P50);
b = addJunction("B", P90, P50);
postCalculate(); // TODO remove
}
public void setMin(final double min) {
this.min = min;
evaluate();
}
public void setMax(final double max) {
this.max = max;
evaluate();
}
@Override
public void postCalculate() {
voltage = !Double.isNaN(b.getVoltage()) && !Double.isNaN(a.getVoltage()) ? b.getVoltage() - a.getVoltage() : 0.0;
final double ratio = (voltage - min) / (max - min);
final double degrees = DEGREES_TOTAL * ratio + DEGREES_ROTATE;
final RealMatrix rotate = RotationMatrix.ofDegrees(degrees);
final RealVector rotatedFinger = rotate.operate(FINGER);
tip = ANCHOR.add(rotatedFinger);
}
@Override
public void _render() {
render.clockwise(getOrientation());
render.line(ABS(ANCHOR), ABS(tip), Color.BLACK, SCALE_STROKE);
}
@Override
protected void _labels() {
render.textCenter(LABEL_FONT, "%.2f V".formatted(voltage), P50, P75, Color.BLACK);
}
@Override
public List<InnerConnection> getInnerConnections() {
return List.of(new InnerConnection(a, b, MAX_RESISTANCE));
}
}

View File

@ -0,0 +1,32 @@
package de.ph87.electro.circuit.part.parts;
import de.ph87.electro.circuit.part.PartDto;
import de.ph87.electro.circuit.part.junction.JunctionDto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@ToString
@NoArgsConstructor
public class VoltmeterDto extends PartDto {
private JunctionDto a;
private JunctionDto b;
@Setter
private double min;
@Setter
private double max;
public VoltmeterDto(final Voltmeter voltmeter) {
a = new JunctionDto(voltmeter.getA());
b = new JunctionDto(voltmeter.getB());
min = voltmeter.getMin();
max = voltmeter.getMax();
}
}

View File

@ -44,6 +44,7 @@ public class Sidebar extends JPanel {
addPart(new Switch1x2(null, Position.ZERO));
addPart(new SwitchCross(null, Position.ZERO));
addPart(new Poti(null, Position.ZERO));
addPart(new Voltmeter(null, Position.ZERO));
}
@SuppressWarnings("UnusedReturnValue")