From 6e919714d3b5f16005ea40c5dc247fbf5eacd277 Mon Sep 17 00:00:00 2001 From: Bane Stojkovic Date: Tue, 11 Mar 2025 23:42:56 +0100 Subject: [PATCH] merged changes --- .../java/org/diylc/common/Orientation.java | 16 +- .../java/org/diylc/common/Orientation45.java | 46 ++++ .../org/diylc/core/images/IconLoader.java | 2 +- ...yzer.java => AbstractNetlistAnalyzer.java} | 4 +- .../main/java/org/diylc/netlist/Netlist.java | 12 +- .../org/diylc/netlist/NetlistBuilder.java | 29 ++- .../src/main/java/org/diylc/netlist/Tree.java | 6 +- .../diylc/presenter/InstantiationManager.java | 10 +- .../java/org/diylc/presenter/Presenter.java | 6 +- .../org/diylc/netlist/TreeAsciiUtilTest.java | 11 + .../connectivity/MultimeterProbe.java | 243 ++++++++++++++++++ .../diylc/netlist/GuitarDiagramAnalyzer.java | 10 +- .../org/diylc/netlist/MultimeterAnalyzer.java | 91 +++++++ .../java/org/diylc/netlist/SpiceAnalyzer.java | 8 +- ...> GuitarAbstractNetlistAnalyzerTests.java} | 2 +- .../main/java/org/diylc/utils/IconLoader.java | 2 +- .../src/main/resources/images/multimeter.png | Bin 0 -> 864 bytes 17 files changed, 438 insertions(+), 60 deletions(-) create mode 100644 diylc/diylc-core/src/main/java/org/diylc/common/Orientation45.java rename diylc/diylc-core/src/main/java/org/diylc/netlist/{NetlistAnalyzer.java => AbstractNetlistAnalyzer.java} (99%) create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/connectivity/MultimeterProbe.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/netlist/MultimeterAnalyzer.java rename diylc/diylc-library/src/test/java/org/diylc/netlist/{GuitarNetlistAnalyzerTests.java => GuitarAbstractNetlistAnalyzerTests.java} (97%) create mode 100644 diylc/diylc-swing/src/main/resources/images/multimeter.png diff --git a/diylc/diylc-core/src/main/java/org/diylc/common/Orientation.java b/diylc/diylc-core/src/main/java/org/diylc/common/Orientation.java index 97901e06..fe16c0ed 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/common/Orientation.java +++ b/diylc/diylc-core/src/main/java/org/diylc/common/Orientation.java @@ -35,19 +35,9 @@ public enum Orientation { } public double toDegrees() { - switch (this) { - case DEFAULT: - return 0; - case _180: - return 180; - case _270: - return 270; - case _90: - return 90; - default: - break; - } - return 0; + if (this == DEFAULT) + return 0; + return Integer.parseInt(name().replace("_", "")); } public double toRadians() { diff --git a/diylc/diylc-core/src/main/java/org/diylc/common/Orientation45.java b/diylc/diylc-core/src/main/java/org/diylc/common/Orientation45.java new file mode 100644 index 00000000..dffdfd8a --- /dev/null +++ b/diylc/diylc-core/src/main/java/org/diylc/common/Orientation45.java @@ -0,0 +1,46 @@ +/* + + DIY Layout Creator (DIYLC). + Copyright (c) 2009-2018 held jointly by the individual authors. + + This file is part of DIYLC. + + DIYLC is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DIYLC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DIYLC. If not, see . + +*/ +package org.diylc.common; + +public enum Orientation45 { + + DEFAULT, _45, _90, _135, _180, _225, _270, _315; + + @Override + public String toString() { + if (this == DEFAULT) { + return "Default"; + } else { + return name().replace("_", "") + " degrees clockwise"; + } + } + + public double toDegrees() { + if (this == DEFAULT) + return 0; + return Integer.parseInt(name().replace("_", "")); + } + + public double toRadians() { + return Math.toRadians(toDegrees()); + } +} diff --git a/diylc/diylc-core/src/main/java/org/diylc/core/images/IconLoader.java b/diylc/diylc-core/src/main/java/org/diylc/core/images/IconLoader.java index d0f0288c..d792f9bb 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/core/images/IconLoader.java +++ b/diylc/diylc-core/src/main/java/org/diylc/core/images/IconLoader.java @@ -72,7 +72,7 @@ public enum IconLoader { BufferedImage img = null; try { img = ImageIO.read(getClass().getResourceAsStream("/images/" + name)); - } catch (IOException e) { + } catch (Exception e) { Logger.getLogger(IconLoader.class).error("Couldn't find file: " + name); } return img; diff --git a/diylc/diylc-core/src/main/java/org/diylc/netlist/NetlistAnalyzer.java b/diylc/diylc-core/src/main/java/org/diylc/netlist/AbstractNetlistAnalyzer.java similarity index 99% rename from diylc/diylc-core/src/main/java/org/diylc/netlist/NetlistAnalyzer.java rename to diylc/diylc-core/src/main/java/org/diylc/netlist/AbstractNetlistAnalyzer.java index 64fd22f3..58c46752 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/netlist/NetlistAnalyzer.java +++ b/diylc/diylc-core/src/main/java/org/diylc/netlist/AbstractNetlistAnalyzer.java @@ -27,9 +27,9 @@ import java.util.Set; import org.diylc.core.IDIYComponent; -public abstract class NetlistAnalyzer { +public abstract class AbstractNetlistAnalyzer { - public NetlistAnalyzer() { + public AbstractNetlistAnalyzer() { } public List summarize(List netlists, Node preferredOutput) diff --git a/diylc/diylc-core/src/main/java/org/diylc/netlist/Netlist.java b/diylc/diylc-core/src/main/java/org/diylc/netlist/Netlist.java index 8c269ccf..49794072 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/netlist/Netlist.java +++ b/diylc/diylc-core/src/main/java/org/diylc/netlist/Netlist.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.diylc.core.IDIYComponent; @@ -59,10 +60,6 @@ public class Netlist implements Comparable { return switchSetup; } - public void done() { - Collections.sort(switchSetup); - } - @Override public int hashCode() { final int prime = 31; @@ -88,10 +85,15 @@ public class Netlist implements Comparable { return true; } + public String getSwitchSetupString() { + return getSwitchSetup().isEmpty() ? "[ ALL ]" : "[ " + + getSwitchSetup().stream().map(x -> x.toString()).collect(Collectors.joining(",")) + " ]"; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("Switch setup: ").append(getSwitchSetup()).append("\n\n"); + sb.append("Switch setup: ").append(getSwitchSetupString()).append("\n\n"); List list = getSortedGroups(); for (Group g : list) { sb.append("\t").append(g).append("\n"); diff --git a/diylc/diylc-core/src/main/java/org/diylc/netlist/NetlistBuilder.java b/diylc/diylc-core/src/main/java/org/diylc/netlist/NetlistBuilder.java index 5178513a..47aa6066 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/netlist/NetlistBuilder.java +++ b/diylc/diylc-core/src/main/java/org/diylc/netlist/NetlistBuilder.java @@ -19,15 +19,7 @@ package org.diylc.netlist; import java.awt.geom.Area; import java.awt.geom.Point2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; import java.util.stream.Collectors; import org.apache.log4j.Logger; @@ -191,10 +183,29 @@ public class NetlistBuilder { // sort everything alphabetically List netlists = new ArrayList(result.keySet()); Collections.sort(netlists); + netlists.forEach(netlist -> cleanupRedundantSwitches(netlist.getSwitchSetup())); return netlists; } + public static void cleanupRedundantSwitches(List switchSetups) { + Map> positionCountMap = new HashMap<>(); + switchSetups.forEach(s -> s.getPositions().forEach(pos -> { + positionCountMap.computeIfAbsent(pos.getSwitch(), k -> new HashSet()).add(pos.getPosition()); + })); + // find switches that are here in all the positions, meaning that they don't affect the circuit + Set switchesToPrune = positionCountMap.entrySet().stream() + .filter(e -> e.getKey().getPositionCount() == e.getValue().size()) + .map(x -> x.getKey()) + .collect(Collectors.toSet()); + switchSetups.forEach(s -> s.getPositions().removeIf(x -> switchesToPrune.contains(x.getSwitch()))); + switchSetups.removeIf(x -> x.getPositions().isEmpty()); + HashSet uniqueSetups = new HashSet<>(switchSetups); + switchSetups.clear(); + switchSetups.addAll(uniqueSetups); + switchSetups.sort(Comparator.comparing(x -> x.toString())); + } + public static Netlist buildNetlist(List> components, Collection nodes, Collection continuityAreas, Collection connections) { ImmutableGraph graph = buildGraph(nodes, continuityAreas, connections); diff --git a/diylc/diylc-core/src/main/java/org/diylc/netlist/Tree.java b/diylc/diylc-core/src/main/java/org/diylc/netlist/Tree.java index 71cebbd5..96173b8b 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/netlist/Tree.java +++ b/diylc/diylc-core/src/main/java/org/diylc/netlist/Tree.java @@ -172,10 +172,10 @@ public class Tree { } public String toAsciiString() { - return String.join("
", toAscii()); + return String.join("
", toAsciiLines()); } - private List toAscii() { + private List toAsciiLines() { if (leaf != null) { return Arrays.asList(TreeAsciiUtil.generateString(TreeAsciiUtil.BOXH, 1) + " " + leaf.toHTML() + " " + TreeAsciiUtil.generateString(TreeAsciiUtil.BOXH, 1)); @@ -184,7 +184,7 @@ public class Tree { List children = getOrderedChildren(); List> childrenAscii = - children.stream().map(c -> c.toAscii()).collect(Collectors.toList()); + children.stream().map(c -> c.toAsciiLines()).collect(Collectors.toList()); if (TreeConnectionType.Series.equals(connectionType)) { return TreeAsciiUtil.concatenateMultiLineSerial( diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/InstantiationManager.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/InstantiationManager.java index a54dbc75..ef28e0cc 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/presenter/InstantiationManager.java +++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/InstantiationManager.java @@ -36,11 +36,7 @@ import org.apache.log4j.Logger; import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.clipboard.ComponentTransferable; -import org.diylc.common.ComponentType; -import org.diylc.common.IPlugInPort; -import org.diylc.common.Orientation; -import org.diylc.common.OrientationHV; -import org.diylc.common.PropertyWrapper; +import org.diylc.common.*; import org.diylc.core.Angle; import org.diylc.core.CreationMethod; import org.diylc.core.IDIYComponent; @@ -437,6 +433,7 @@ public class InstantiationManager { for (PropertyWrapper propertyWrapper : properties) { if (propertyWrapper.getType().getName().equals(Orientation.class.getName()) || propertyWrapper.getType().getName().equals(OrientationHV.class.getName()) + || propertyWrapper.getType().getName().equals(Orientation45.class.getName()) || propertyWrapper.getName().equalsIgnoreCase("angle")) { angleProperty = propertyWrapper; break; @@ -456,6 +453,9 @@ public class InstantiationManager { } else if (value instanceof OrientationHV) { angleProperty.setValue(OrientationHV.values()[(((OrientationHV) value).ordinal() + 1) % OrientationHV.values().length]); + } else if (value instanceof Orientation45) { + angleProperty.setValue(Orientation45.values()[(((Orientation45) value).ordinal() + 1) + % Orientation45.values().length]); } else if (value instanceof Angle) { Angle angle = (Angle) angleProperty.getValue(); Angle newAngle = angle.rotate(1); diff --git a/diylc/diylc-core/src/main/java/org/diylc/presenter/Presenter.java b/diylc/diylc-core/src/main/java/org/diylc/presenter/Presenter.java index a1f57634..a8b9c3b3 100644 --- a/diylc/diylc-core/src/main/java/org/diylc/presenter/Presenter.java +++ b/diylc/diylc-core/src/main/java/org/diylc/presenter/Presenter.java @@ -32,7 +32,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Modifier; -import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -50,7 +49,6 @@ import javax.swing.JOptionPane; import org.apache.log4j.Logger; import org.diylc.appframework.miscutils.IConfigListener; import org.diylc.appframework.miscutils.IConfigurationManager; -import org.diylc.appframework.miscutils.JarScanner; import org.diylc.appframework.miscutils.Utils; import org.diylc.appframework.simplemq.MessageDispatcher; import org.diylc.appframework.update.Version; @@ -88,7 +86,7 @@ import org.diylc.core.measures.SizeUnit; import org.diylc.lang.LangUtil; import org.diylc.netlist.INetlistParser; import org.diylc.netlist.Netlist; -import org.diylc.netlist.NetlistAnalyzer; +import org.diylc.netlist.AbstractNetlistAnalyzer; import org.diylc.netlist.NetlistBuilder; import org.diylc.netlist.NetlistException; import org.diylc.serialization.ProjectFileManager; @@ -2030,7 +2028,7 @@ public class Presenter implements IPlugInPort, IConfigListener { if (netlists == null) return; - List>> allGroups = NetlistAnalyzer.extractComponentGroups(netlists); + List>> allGroups = AbstractNetlistAnalyzer.extractComponentGroups(netlists); // Find control points of all selected components and all types Set selectedNamePrefixes = new HashSet(); if (expansionMode == ExpansionMode.SAME_TYPE) { diff --git a/diylc/diylc-core/src/test/java/org/diylc/netlist/TreeAsciiUtilTest.java b/diylc/diylc-core/src/test/java/org/diylc/netlist/TreeAsciiUtilTest.java index 8868d801..5c00ee58 100644 --- a/diylc/diylc-core/src/test/java/org/diylc/netlist/TreeAsciiUtilTest.java +++ b/diylc/diylc-core/src/test/java/org/diylc/netlist/TreeAsciiUtilTest.java @@ -56,4 +56,15 @@ public class TreeAsciiUtilTest { // assertEquals("yy-yyy", result.get(1)); // assertEquals("   aaa", result.get(2)); } + + @Test + public void testSimpleParallel() { + List result = TreeAsciiUtil.concatenateMultiLineParallel( + Arrays.asList(Arrays.asList("xx"), Arrays.asList("yy"))); + assertNotNull(result); + assertEquals(3, result.size()); + assertEquals(" ┌xx┐ ", result.get(0)); + assertEquals("─┤  ├─", result.get(1)); + assertEquals(" └yy┘ ", result.get(2)); + } } diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/MultimeterProbe.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/MultimeterProbe.java new file mode 100644 index 00000000..3eb6efe1 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/MultimeterProbe.java @@ -0,0 +1,243 @@ +/* + * + * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with DIYLC. If not, see + * . + * + */ +package org.diylc.components.connectivity; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation45; +import org.diylc.components.AbstractTransparentComponent; +import org.diylc.components.transform.SimpleComponentTransformer; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.VisibilityPolicy; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.EditableProperty; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; + +@ComponentDescriptor(name = "Multimeter Probe", category = "Connectivity", + author = "Branislav Stojkovic", description = "Multimeter Probe", instanceNamePrefix = "Probe", + zOrder = IDIYComponent.TEXT, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, + keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = SimpleComponentTransformer.class, + enableCache = true) +public class MultimeterProbe extends AbstractTransparentComponent { + + private static final long serialVersionUID = 1L; + + public static Size PROBE_DIAMETER = new Size(0.05d, SizeUnit.in); + public static Size PROBE_LENGTH = new Size(0.4d, SizeUnit.in); + public static Color PROBE_COLOR = METAL_COLOR; + public static Size HANDLE_DIAMETER = new Size(0.2d, SizeUnit.in); + public static Size HANDLE_LENGTH = new Size(0.4d, SizeUnit.in); + public static Color HANDLE_COLOR = Color.red; + + private Point2D.Double point = new Point2D.Double(0, 0); + private Color handleColor = HANDLE_COLOR; + private Orientation45 orientation = Orientation45._315; + + private transient Shape[] body = null; + + public MultimeterProbe() { + this.alpha = (byte) (MAX_ALPHA / 2); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, + Project project, IDrawingObserver drawingObserver) { + + Shape[] shapes = getBody(); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f)); + + if (!outlineMode) { + Composite oldComposite = g2d.getComposite(); + if (alpha < MAX_ALPHA) { + g2d.setComposite( + AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA)); + } + g2d.setColor(PROBE_COLOR); + g2d.fill(shapes[0]); + g2d.setColor(handleColor); + g2d.fill(shapes[1]); + g2d.setComposite(oldComposite); + } + g2d.setColor( + componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING + ? SELECTION_COLOR + : handleColor.darker()); + g2d.draw(shapes[1]); + g2d.setColor( + componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING + ? SELECTION_COLOR + : PROBE_COLOR.darker()); + g2d.draw(shapes[0]); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + double probeDiameter = 2; + double probeLength = height / 2 + 2; + double handleDiameter = width / 4; + double handleLength = height / 2 + 2; + double x = 2; + double y = height - 2; + Shape probe = buildProbeShape(probeDiameter, probeLength, x, y); + Shape handle = buildHandleShape(probeDiameter, probeLength, handleDiameter, handleLength, x, y); + + double theta = Math.PI / 4; + AffineTransform tx = AffineTransform.getRotateInstance(theta, x, y); + probe = tx.createTransformedShape(probe); + handle = tx.createTransformedShape(handle); + + g2d.setColor(PROBE_COLOR); + g2d.fill(probe); + g2d.setColor(HANDLE_COLOR); + g2d.fill(handle); + + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + g2d.setColor(PROBE_COLOR.darker()); + g2d.draw(probe); + g2d.setColor(HANDLE_COLOR.darker()); + g2d.draw(handle); + } + + public Shape[] getBody() { + if (body == null) { + double probeDiameter = PROBE_DIAMETER.convertToPixels(); + double probeLength = PROBE_LENGTH.convertToPixels(); + double handleDiameter = HANDLE_DIAMETER.convertToPixels(); + double handleLength = HANDLE_LENGTH.convertToPixels(); + double x = point.getX(); + double y = point.getY(); + body = new Shape[2]; + Path2D probe = buildProbeShape(probeDiameter, probeLength, x, y); + body[0] = probe; + Path2D handle = + buildHandleShape(probeDiameter, probeLength, handleDiameter, handleLength, x, y); + body[1] = handle; + + double theta = orientation.toRadians(); + if (theta != 0) { + AffineTransform tx = AffineTransform.getRotateInstance(theta, x, y); + body[0] = tx.createTransformedShape(body[0]); + body[1] = tx.createTransformedShape(body[1]); + } + } + return body; + } + + private Path2D buildHandleShape(double probeDiameter, double probeLength, double handleDiameter, + double handleLength, double x, double y) { + Path2D handle = new Path2D.Double(); + handle.moveTo(x + probeDiameter, y - probeLength); + handle.lineTo(x + handleDiameter / 2, y - handleLength - probeLength); + handle.lineTo(x - handleDiameter / 2, y - handleLength - probeLength); + handle.lineTo(x - probeDiameter, y - probeLength); + handle.moveTo(x + probeDiameter, y - probeLength); + handle.closePath(); + return handle; + } + + private Path2D buildProbeShape(double probeDiameter, double probeLength, double x, double y) { + Path2D probe = new Path2D.Double(); + probe.moveTo(x, y); + probe.lineTo(x - probeDiameter / 2, y - probeDiameter); + probe.lineTo(x - probeDiameter / 2, y - probeLength); + probe.lineTo(x + probeDiameter / 2, y - probeLength); + probe.lineTo(x + probeDiameter / 2, y - probeDiameter); + probe.lineTo(x, y); + probe.closePath(); + return probe; + } + + @Override + public int getControlPointCount() { + return 1; + } + + @Override + public boolean isControlPointSticky(int index) { + return true; + } + + @Override + public VisibilityPolicy getControlPointVisibilityPolicy(int index) { + return VisibilityPolicy.NEVER; + } + + @Override + public Point2D getControlPoint(int index) { + return point; + } + + @Override + public void setControlPoint(Point2D point, int index) { + this.point.setLocation(point); + this.body = null; + } + + @Override + @EditableProperty(name = "Color") + public Color getValue() { + return handleColor; + } + + public void setValue(Color color) { + this.handleColor = color; + } + + @EditableProperty(name = "Angle") + public Orientation45 getOrientation() { + return orientation; + } + + public void setOrientation(Orientation45 orientation) { + this.orientation = orientation; + this.body = null; + } + + @Override + public String getControlPointNodeName(int index) { + return "Tip"; + } + + @Override + public Rectangle2D getCachingBounds() { + Shape[] shapes = getBody(); + Rectangle2D bounds1 = shapes[0].getBounds2D(); + Rectangle2D bounds2 = shapes[1].getBounds2D(); + double minX = Math.min(bounds1.getMinX(), bounds2.getMinX()); + double minY = Math.min(bounds1.getMinY(), bounds2.getMinY()); + double maxX = Math.max(bounds1.getMaxX(), bounds2.getMaxX()); + double maxY = Math.max(bounds1.getMaxY(), bounds2.getMaxY()); + return new Rectangle2D.Double(minX - 1, minY - 1, maxX - minX + 2, maxY - minY + 2); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/netlist/GuitarDiagramAnalyzer.java b/diylc/diylc-library/src/main/java/org/diylc/netlist/GuitarDiagramAnalyzer.java index 8d178706..b0dc53f9 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/netlist/GuitarDiagramAnalyzer.java +++ b/diylc/diylc-library/src/main/java/org/diylc/netlist/GuitarDiagramAnalyzer.java @@ -46,17 +46,9 @@ import org.diylc.components.passive.RadialFilmCapacitor; import org.diylc.components.passive.RadialMicaCapacitor; import org.diylc.components.passive.Resistor; import org.diylc.core.IDIYComponent; -import org.diylc.netlist.Netlist; -import org.diylc.netlist.NetlistAnalyzer; -import org.diylc.netlist.Node; -import org.diylc.netlist.Summary; -import org.diylc.netlist.Tree; -import org.diylc.netlist.TreeConnectionType; -import org.diylc.netlist.TreeException; -import org.diylc.netlist.TreeLeaf; import org.diylc.netlist.Tree.ITreeWalker; -public class GuitarDiagramAnalyzer extends NetlistAnalyzer implements INetlistAnalyzer { +public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements INetlistAnalyzer { private static Set JACK_TYPES = new HashSet(); private static Set POT_TYPES = new HashSet(); diff --git a/diylc/diylc-library/src/main/java/org/diylc/netlist/MultimeterAnalyzer.java b/diylc/diylc-library/src/main/java/org/diylc/netlist/MultimeterAnalyzer.java new file mode 100644 index 00000000..0080ccbf --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/netlist/MultimeterAnalyzer.java @@ -0,0 +1,91 @@ +/* + * + * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with DIYLC. If not, see + * . + * + */ +package org.diylc.netlist; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import javax.swing.JLabel; +import org.diylc.common.INetlistAnalyzer; +import org.diylc.components.connectivity.MultimeterProbe; + +public class MultimeterAnalyzer extends AbstractNetlistAnalyzer implements INetlistAnalyzer { + + @Override + public String getName() { + return "Virtual Multimeter"; + } + + @Override + public String getShortName() { + return "multimeter"; + } + + @Override + public String getIconName() { + return "Multimeter"; + } + + @Override + public String getFontName() { + return new JLabel().getFont().getName(); + } + + protected Summary summarize(Netlist netlist, Node preferredOutput) throws TreeException { + Tree tree = constructTree(netlist); + + if (tree == null) { + return new Summary(netlist, "No components found connecting the two multimeter probes."); + } + + List notes = new ArrayList(); + + StringBuilder sb = new StringBuilder(); + + String asciiTree = tree.toAsciiString(); + + sb.append("

") + .append("") + .append(asciiTree) + .append(""); + if (!notes.isEmpty()) { + Collections.sort(notes); + sb.append("

"); + for (String v : notes) { + sb.append(v).append("
"); + } + } + + return new Summary(netlist, sb.toString()); + } + + public Tree constructTree(Netlist netlist) throws TreeException { + List probeNodes = find(Set.of(MultimeterProbe.class.getCanonicalName()), null, netlist); + + if (probeNodes.isEmpty()) { + throw new TreeException("No multimeter probes are placed on the circuit."); + } else if (probeNodes.size() != 2) { + throw new TreeException( + "Place exactly two multimeter probes on the circuit in order to run the analysis."); + } else { + return constructTreeBetween(netlist, probeNodes.get(0), probeNodes.get(1)); + } + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/netlist/SpiceAnalyzer.java b/diylc/diylc-library/src/main/java/org/diylc/netlist/SpiceAnalyzer.java index 7ba4652b..642ca708 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/netlist/SpiceAnalyzer.java +++ b/diylc/diylc-library/src/main/java/org/diylc/netlist/SpiceAnalyzer.java @@ -27,14 +27,8 @@ import java.util.stream.Collectors; import org.diylc.common.INetlistAnalyzer; import org.diylc.core.IDIYComponent; -import org.diylc.netlist.Group; -import org.diylc.netlist.Netlist; -import org.diylc.netlist.NetlistAnalyzer; -import org.diylc.netlist.Node; -import org.diylc.netlist.Summary; -import org.diylc.netlist.TreeException; -public class SpiceAnalyzer extends NetlistAnalyzer implements INetlistAnalyzer { +public class SpiceAnalyzer extends AbstractNetlistAnalyzer implements INetlistAnalyzer { public SpiceAnalyzer() { } diff --git a/diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java b/diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarAbstractNetlistAnalyzerTests.java similarity index 97% rename from diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java rename to diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarAbstractNetlistAnalyzerTests.java index 0ef96c6f..3e1aff50 100644 --- a/diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java +++ b/diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarAbstractNetlistAnalyzerTests.java @@ -34,7 +34,7 @@ import org.diylc.netlist.Netlist; import org.diylc.netlist.Tree; import org.diylc.netlist.TreeException; -public class GuitarNetlistAnalyzerTests { +public class GuitarAbstractNetlistAnalyzerTests { @Test public void testOneSinglePickup() throws TreeException { diff --git a/diylc/diylc-swing/src/main/java/org/diylc/utils/IconLoader.java b/diylc/diylc-swing/src/main/java/org/diylc/utils/IconLoader.java index 54574782..6969ad18 100644 --- a/diylc/diylc-swing/src/main/java/org/diylc/utils/IconLoader.java +++ b/diylc/diylc-swing/src/main/java/org/diylc/utils/IconLoader.java @@ -71,7 +71,7 @@ public enum IconLoader { SnapToComponents("snap_to_components.png"), SnapToNone("snap_to_none.png"), TraceProximity("trace_proximity.png"), ComponentLarge("component_large.png"), ImportNetlist("import_netlist.png"), SplashIC("splash_ic.png"), ComponentPreferences("component_preferences.png"), ComponentReplace("component_replace.png"), Barcode("barcode.png"), - DocumentGerber("document_gerber.png"), DocumentX2("document_x2.png"), Export("export.png"); + DocumentGerber("document_gerber.png"), DocumentX2("document_x2.png"), Export("export.png"), Multimeter("multimeter.png"); protected String name; diff --git a/diylc/diylc-swing/src/main/resources/images/multimeter.png b/diylc/diylc-swing/src/main/resources/images/multimeter.png new file mode 100644 index 0000000000000000000000000000000000000000..4454b9689deee14716a996945e588809de812364 GIT binary patch literal 864 zcmV-m1E2hfP)WdKHUATc>0L}hv)GB7YRATTjHG&4FhIUp-AF)%O>gyEO~000McNliru z)&&<0GAXKu>WTmW010qNS#tmY3h)2`3h)6!tTdPa000DMK}|sb0I`n?{9y$E00Ov4 zL_t(|+GSI_ZWBQiJ>%II8ypfrco{)M5KSmZK?6;I5>bPw_z6A%A@K`TP*TxRA(8@6 z5F%0(CrX?k#pV%*IQDvXc4z0o9kWItRyx|9**WJv&K-u|PwoD_`*-7L;!fxVSFB}c zjWNfRQeKf4MOl`;LW)+BCGR@lJI|ZV<_>Wr!7|5w^7zS82L}hG)&_Z=!B|7E5IP@aplk^P4Z|#q2GT5T6GyrF9oGpUP16-wNDQ+9GCe?F z{zRhoAt-%~k~*c)GvBB**N@?Mq6`S7$K8rhrl<6@p?EVJu*c)uk$t ziUeQO3O4gq)EGzL1*m&d2!a4n6pb3ImGP_k?H_?!jU9IaTzjZb)^UQL0Amau=inZP z?~@R@$7|d*+4YTA28;!2vx){wu10vf{2t^RbZIGK4U8(anvoFDdLa={Mi+WR1pf$7 zE?koTwi6+IHiylP78Y(UU}^C!W-rZRkkB0XoXqcIjqMyI$|S)b&w=fHZGS9Dz(2w< zeYTE?lRnnIe1`Nhw7zX%cYhngCdf;g6JuQTs4C<4U6`4fx!h)B7=}|qh=2}K z$CZ*&X0-0ny6AShTlC(ib4|iaLYq}Ky0N@SxJEeduE$>%o62)%og3q?mB5Buj|EsI qa*Qxhr8oXJwoF$eEGnVg?f(KZ&Vsxw`i6i20000