diff --git a/diylc/diylc-core/src/org/diylc/netlist/Tree.java b/diylc/diylc-core/src/org/diylc/netlist/Tree.java index dbaf7246..33dc26f3 100644 --- a/diylc/diylc-core/src/org/diylc/netlist/Tree.java +++ b/diylc/diylc-core/src/org/diylc/netlist/Tree.java @@ -30,6 +30,11 @@ public class Tree { private TreeConnectionType connectionType; private TreeLeaf leaf; + public Tree(TreeConnectionType connectionType) { + this.children = new ArrayList(); + this.connectionType = connectionType; + } + public Tree(TreeLeaf leaf) { this.leaf = leaf; } @@ -43,9 +48,13 @@ public class Tree { return children; } - public void trimChildren(int count) { + public void trimChildrenLeft(int count) { children = children.subList(count, children.size()); } + + public void trimChildrenRight(int count) { + children = children.subList(0, children.size() - count); + } public TreeConnectionType getConnectionType() { return connectionType; diff --git a/diylc/diylc-core/src/org/diylc/netlist/TreeLeaf.java b/diylc/diylc-core/src/org/diylc/netlist/TreeLeaf.java index f6135947..c2308e31 100644 --- a/diylc/diylc-core/src/org/diylc/netlist/TreeLeaf.java +++ b/diylc/diylc-core/src/org/diylc/netlist/TreeLeaf.java @@ -92,7 +92,10 @@ public class TreeLeaf implements ITree { @Override public String toString() { - return component.getName() + "." + component.getInternalLinkName(pointIndex1, pointIndex2); + String linkName = component.getInternalLinkName(pointIndex1, pointIndex2); + if (component.getName().equals(linkName)) + return linkName; + return component.getName() + "." + linkName; } public String toHTML() { diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar index c61dc191..57a48d4c 100644 Binary files a/diylc/diylc-library/lib/diylc-core.jar and b/diylc/diylc-library/lib/diylc-core.jar differ diff --git a/diylc/diylc-library/src/org/diylc/components/AbstractLeadedComponent.java b/diylc/diylc-library/src/org/diylc/components/AbstractLeadedComponent.java index 5fb28ef3..0bfd69f3 100644 --- a/diylc/diylc-library/src/org/diylc/components/AbstractLeadedComponent.java +++ b/diylc/diylc-library/src/org/diylc/components/AbstractLeadedComponent.java @@ -130,6 +130,7 @@ public abstract class AbstractLeadedComponent extends AbstractTransparentComp : borderColor; } + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f)); g2d.setColor(finalBorderColor); g2d.draw(body); if (!outlineMode) { diff --git a/diylc/diylc-library/src/org/diylc/netlist/AbstractNetlistAnalyzer.java b/diylc/diylc-library/src/org/diylc/netlist/AbstractNetlistAnalyzer.java index a9fb74f9..b4ec4a2f 100644 --- a/diylc/diylc-library/src/org/diylc/netlist/AbstractNetlistAnalyzer.java +++ b/diylc/diylc-library/src/org/diylc/netlist/AbstractNetlistAnalyzer.java @@ -1,143 +1,224 @@ /* - - 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 . - -*/ + * + * 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.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 org.diylc.core.IDIYComponent; public abstract class AbstractNetlistAnalyzer { - public AbstractNetlistAnalyzer() { - } - - protected Tree constructTree(Netlist netlist, Node nodeA, Node nodeB) { - Tree tree = new Tree(new ArrayList(), TreeConnectionType.Parallel); - connectNodes(netlist, nodeA, nodeB, tree.getChildren(), null, new HashSet()); -// System.out.println(netlist.getSwitchSetup()); -// System.out.println(tree); + public AbstractNetlistAnalyzer() {} + + protected Tree constructTreeBetween(Netlist netlist, Node nodeA, Node nodeB) { + Tree tree = new Tree(TreeConnectionType.Parallel); + connectNodes(netlist, nodeA, nodeB, tree.getChildren(), new Tree(TreeConnectionType.Series), new HashSet()); + + // System.out.println(netlist.getSwitchSetup()); + // System.out.println(tree); + // + // System.out.println("opposite:"); + // Tree tree1 = new Tree(TreeConnectionType.Parallel); + // connectNodes(netlist, nodeB, nodeA, tree1.getChildren(), new Tree(TreeConnectionType.Series), + // new HashSet()); + // System.out.println(tree1); + return tree; } - - protected void connectNodes(Netlist netlist, Node nodeA, Node nodeB, List concurrentPaths, Tree currentPath, Set visited) { + + protected void connectNodes(Netlist netlist, Node nodeA, Node nodeB, List concurrentPaths, Tree currentPath, + Set visited) { if (nodeA == nodeB) { concurrentPaths.add(currentPath); return; - } - + } + Group groupA = findGroup(netlist, nodeA); - + if (groupA == null) return; - + if (groupA.getNodes().contains(nodeB)) { concurrentPaths.add(currentPath); return; } - - visited.add(nodeA); - + + visited.addAll(groupA.getNodes()); + + List newConcurrentPaths = new ArrayList(); + for (Node n : groupA.getNodes()) { IDIYComponent c = n.getComponent(); for (int i = 0; i < c.getControlPointCount(); i++) { if (i != n.getPointIndex() && c.getInternalLinkName(i, n.getPointIndex()) != null) { TreeLeaf l = new TreeLeaf(c, i, n.getPointIndex()); Node newNodeA = new Node(c, i); - if (!visited.contains(newNodeA)) { - visited.add(n); + if (!visited.contains(newNodeA)) { + // visited.add(n); Tree newCurrentPath = null; try { - if (currentPath == null) - newCurrentPath = new Tree(new ArrayList(), TreeConnectionType.Series); - else - newCurrentPath = (Tree) currentPath.clone(); + newCurrentPath = (Tree) currentPath.clone(); } catch (CloneNotSupportedException e) { } Tree newItem = new Tree(l); if (!newCurrentPath.getChildren().contains(newItem)) newCurrentPath.getChildren().add(newItem); -// if (!currentPath.contains(l)) -// newCurrentPath.add(l); + // if (!currentPath.contains(l)) + // newCurrentPath.add(l); Set newVisited = new HashSet(visited); - connectNodes(netlist, newNodeA, nodeB, concurrentPaths, newCurrentPath, newVisited); + connectNodes(netlist, newNodeA, nodeB, newConcurrentPaths, newCurrentPath, newVisited); } } } } - - if (concurrentPaths.size() < 2) + + if (newConcurrentPaths.size() == 0) return; + + + if (newConcurrentPaths.size() == 1) { + if (newConcurrentPaths.get(0).getConnectionType() == TreeConnectionType.Series) { + currentPath.getChildren().clear(); + currentPath.getChildren().addAll(newConcurrentPaths.get(0).getChildren()); + } else { + currentPath.getChildren().add(newConcurrentPaths.get(0)); + } + concurrentPaths.add(currentPath); + return; + } + + mergePaths(newConcurrentPaths, false); + concurrentPaths.addAll(newConcurrentPaths); + } + + protected void mergePaths(List paths, boolean backward) { + Map uniques = new HashMap(); + for (Tree t : paths) { + if (t.getConnectionType() != TreeConnectionType.Series) + continue; + Tree key = t.getChildren().get(backward ? t.getChildren().size() - 1 : 0); + Integer count = uniques.get(key); + uniques.put(key, count == null ? 1 : count + 1); + } - Tree jointSection = new Tree(new ArrayList(), TreeConnectionType.Series); - for (int i = 0; i < concurrentPaths.get(0).getChildren().size(); i++) { - Tree unique = concurrentPaths.get(0).getChildren().get(i); - boolean canMerge = true; - for (Tree t : concurrentPaths) { - if (t.getConnectionType() != TreeConnectionType.Series || t.getChildren().size() <= i || !t.getChildren().get(i).equals(unique)) { - canMerge = false; - break; + List unmerged = new ArrayList(paths); + + for (Map.Entry e : uniques.entrySet()) { + if (e.getValue() > 1) { + List pathsToMerge = new ArrayList(); + for (Tree t : paths) { + Tree key = t.getChildren().get(backward ? t.getChildren().size() - 1 : 0); + if (key.equals(e.getKey())) + pathsToMerge.add(t); + } + unmerged.removeAll(pathsToMerge); + + Tree jointStart = new Tree(new ArrayList(), TreeConnectionType.Series); + Tree jointFinish = new Tree(new ArrayList(), TreeConnectionType.Series); + + Tree unique = e.getKey(); + + for (int i = 0; i < pathsToMerge.get(0).getChildren().size(); i++) { + boolean canMerge = true; + unique = pathsToMerge.get(0).getChildren().get(backward ? pathsToMerge.get(0).getChildren().size() - i - 1 : i); + for (Tree t : pathsToMerge) { + if (t.getChildren().size() <= i || !t.getChildren().get(backward ? t.getChildren().size() - i - 1 : i).equals(unique)) { + canMerge = false; + break; + } + } + if (canMerge) + (backward ? jointFinish : jointStart).getChildren().add(unique); + else + break; + } + + for (int i = 0; i < pathsToMerge.get(0).getChildren().size(); i++) { + boolean canMerge = true; + unique = pathsToMerge.get(0).getChildren().get(backward ? i : pathsToMerge.get(0).getChildren().size() - i - 1); + for (Tree t : pathsToMerge) { + if (t.getChildren().size() <= i || !t.getChildren().get(backward ? 0 : pathsToMerge.get(0).getChildren().size() - 1).equals(unique)) { + canMerge = false; + break; + } + } + if (canMerge) + (backward ? jointStart : jointFinish).getChildren().add(unique); + else + break; + } + + if (!jointStart.getChildren().isEmpty() || !jointFinish.getChildren().isEmpty()) { + Tree mergedTree = new Tree(new ArrayList(), TreeConnectionType.Series); + Tree parallelSection = new Tree(new ArrayList(pathsToMerge), TreeConnectionType.Parallel); + if (!jointStart.getChildren().isEmpty()) { + mergedTree.getChildren().add(jointStart); + for (Tree t : parallelSection.getChildren()) { + t.trimChildrenLeft(jointStart.getChildren().size()); + } + } + mergedTree.getChildren().add(parallelSection); + if (!jointFinish.getChildren().isEmpty()) { + mergedTree.getChildren().add(jointFinish); + for (Tree t : parallelSection.getChildren()) { + t.trimChildrenRight(jointFinish.getChildren().size()); + } + } + paths.removeAll(pathsToMerge); + paths.add(mergedTree); } } - if (canMerge) - jointSection.getChildren().add(unique); - else - break; } - if (!jointSection.getChildren().isEmpty()) { - Tree mergedTree = new Tree(new ArrayList(), TreeConnectionType.Series); - mergedTree.getChildren().add(jointSection); - Tree parallelSection = new Tree(new ArrayList(concurrentPaths), TreeConnectionType.Parallel); - for (Tree t : parallelSection.getChildren()) { - t.trimChildren(jointSection.getChildren().size()); - } - mergedTree.getChildren().add(parallelSection); - concurrentPaths.clear(); - concurrentPaths.add(mergedTree); + + // try in the opposite direction for paths we haven't merged + if (!backward && !unmerged.isEmpty()) { + paths.removeAll(unmerged); + mergePaths(unmerged, true); + paths.addAll(unmerged); } } - - protected void findAllPaths(Netlist netlist, Node nodeA, Node nodeB, List currentPath, List> allPaths, Set visited) { + + protected void findAllPaths(Netlist netlist, Node nodeA, Node nodeB, List currentPath, + List> allPaths, Set visited) { if (nodeA == nodeB) { allPaths.add(currentPath); return; } - -// System.out.println("Finding path between " + nodeA + " and " + nodeB); - + + // System.out.println("Finding path between " + nodeA + " and " + nodeB); + Group groupA = findGroup(netlist, nodeA); - + if (groupA == null) return; - + if (groupA.getNodes().contains(nodeB)) { allPaths.add(currentPath); return; } - + for (Node n : groupA.getNodes()) { IDIYComponent c = n.getComponent(); for (int i = 0; i < c.getControlPointCount(); i++) { @@ -157,7 +238,7 @@ public abstract class AbstractNetlistAnalyzer { } } } - + protected Group findGroup(Netlist netlist, Node node) { for (Group g : netlist.getGroups()) if (g.getNodes().contains(node)) @@ -169,75 +250,76 @@ public abstract class AbstractNetlistAnalyzer { List res = new ArrayList(); for (Group g : netlist.getGroups()) { for (Node n : g.getNodes()) { - if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) && - (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { + if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) + && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { res.add(g); break; } - } + } } return res; } - + protected List find(Set typeNames, String nodeName, Group group) { List res = new ArrayList(); - for (Node n : group.getNodes()) { - if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) && - (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { + for (Node n : group.getNodes()) { + if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) + && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { res.add(n); } - } - + } + return res; } - + protected List findGroups(Set typeNames, String nodeName, Netlist netlist) { List res = new ArrayList(); for (Group g : netlist.getGroups()) { - for (Node n : g.getNodes()) { - if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) && - (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { + for (Node n : g.getNodes()) { + if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) + && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { res.add(g); break; } - } + } } return res; } - - protected List findGroups(Set typeNames, String nodeName, Netlist netlist, Collection> belongTo) { + + protected List findGroups(Set typeNames, String nodeName, Netlist netlist, + Collection> belongTo) { List res = new ArrayList(); for (Group g : netlist.getGroups()) { - for (Node n : g.getNodes()) { - if ((belongTo == null || belongTo.contains(n.getComponent())) && - (typeNames.contains(n.getComponent().getClass().getCanonicalName())) && - (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { + for (Node n : g.getNodes()) { + if ((belongTo == null || belongTo.contains(n.getComponent())) + && (typeNames.contains(n.getComponent().getClass().getCanonicalName())) + && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { res.add(g); break; } - } + } } return res; } - + protected List find(Set typeNames, String nodeName, Netlist netlist) { List res = new ArrayList(); for (Group g : netlist.getGroups()) { - for (Node n : g.getNodes()) { - if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) && - (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { + for (Node n : g.getNodes()) { + if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) + && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { res.add(n); } - } + } } return res; } - + protected List find(Set typeNames, String nodeName, Netlist netlist, List inGroupWith) { List res = new ArrayList(); for (Group g : netlist.getGroups()) { - + boolean inGroup; if (inGroupWith == null) { inGroup = true; @@ -249,55 +331,57 @@ public abstract class AbstractNetlistAnalyzer { break; } } - - for (Node n : g.getNodes()) { - if (inGroup && typeNames.contains(n.getComponent().getClass().getCanonicalName()) && - (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { + + for (Node n : g.getNodes()) { + if (inGroup && typeNames.contains(n.getComponent().getClass().getCanonicalName()) + && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { res.add(n); } - } + } } return res; } - - protected List find(Set typeNames, String nodeName, Netlist netlist, Collection> belongTo) { + + protected List find(Set typeNames, String nodeName, Netlist netlist, + Collection> belongTo) { List res = new ArrayList(); - for (Group g : netlist.getGroups()) { - - for (Node n : g.getNodes()) { - if ((belongTo == null || belongTo.contains(n.getComponent())) && typeNames.contains(n.getComponent().getClass().getCanonicalName()) && - (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { + for (Group g : netlist.getGroups()) { + + for (Node n : g.getNodes()) { + if ((belongTo == null || belongTo.contains(n.getComponent())) + && typeNames.contains(n.getComponent().getClass().getCanonicalName()) + && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { res.add(n); } - } + } } return res; } - + protected boolean allMatch(Collection nodes, String name) { for (Node n : nodes) if (!n.getDisplayName().equalsIgnoreCase(name)) return false; - + return true; } - + protected boolean allComponentsMatch(Collection nodes, Set> components) { Set> extracted = extractComponents(nodes); return extracted.containsAll(components); } - + protected Set> extractComponents(Collection nodes) { Set> components = new HashSet>(); for (Node n : nodes) components.add(n.getComponent()); return components; } - + protected String extractName(IDIYComponent c) { return c.getName() + " " + c.getValueForDisplay(); } - + protected List extractNames(Collection> components) { List names = new ArrayList(); for (IDIYComponent c : components) @@ -305,13 +389,13 @@ public abstract class AbstractNetlistAnalyzer { Collections.sort(names); return names; } - + protected Netlist simplify(Netlist netlist, Set nodesToMerge, Collection nodesToPurge) { Netlist res = new Netlist(); res.getSwitchSetup().addAll(netlist.getSwitchSetup()); Group merged = new Group(); - + // merge for (Group g : netlist.getGroups()) { boolean needsMerging = false; @@ -330,28 +414,28 @@ public abstract class AbstractNetlistAnalyzer { res.getGroups().add(g.clone()); } } - + if (!merged.getNodes().isEmpty()) res.getGroups().add(merged); - + // purge for (Group g : res.getGroups()) { g.getNodes().removeAll(nodesToPurge); } - + System.out.println("Before:\n" + netlist); System.out.println("After:\n" + res); - + return res; } - + protected boolean intersect(List groups, Node node) { for (Group g : groups) if (g.getNodes().contains(node)) return true; return false; } - + protected Node intersect(List groups, Group group) { for (Group g : groups) for (Node node : group.getNodes()) diff --git a/diylc/diylc-library/src/org/diylc/netlist/GuitarDiagramAnalyzer.java b/diylc/diylc-library/src/org/diylc/netlist/GuitarDiagramAnalyzer.java index 98b81cda..58c8e350 100644 --- a/diylc/diylc-library/src/org/diylc/netlist/GuitarDiagramAnalyzer.java +++ b/diylc/diylc-library/src/org/diylc/netlist/GuitarDiagramAnalyzer.java @@ -164,7 +164,7 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN } else { Node jackTip = jackTipNodes.get(0); Node jackSleeve = jackSleeveNodes.get(0); - return constructTree(netlist, jackTip, jackSleeve); + return constructTreeBetween(netlist, jackTip, jackSleeve); } } } diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar index c61dc191..57a48d4c 100644 Binary files a/diylc/diylc-swing/lib/diylc-core.jar and b/diylc/diylc-swing/lib/diylc-core.jar differ diff --git a/diylc/diylc-swing/library/main.jar b/diylc/diylc-swing/library/main.jar index f7145a03..c6e00727 100644 Binary files a/diylc/diylc-swing/library/main.jar and b/diylc/diylc-swing/library/main.jar differ