tree construction improvement

This commit is contained in:
Branislav Stojkovic
2019-02-24 13:15:30 +01:00
parent c0dac1a1db
commit 0d007e5737
8 changed files with 234 additions and 137 deletions
@@ -30,6 +30,11 @@ public class Tree {
private TreeConnectionType connectionType; private TreeConnectionType connectionType;
private TreeLeaf leaf; private TreeLeaf leaf;
public Tree(TreeConnectionType connectionType) {
this.children = new ArrayList<Tree>();
this.connectionType = connectionType;
}
public Tree(TreeLeaf leaf) { public Tree(TreeLeaf leaf) {
this.leaf = leaf; this.leaf = leaf;
} }
@@ -43,10 +48,14 @@ public class Tree {
return children; return children;
} }
public void trimChildren(int count) { public void trimChildrenLeft(int count) {
children = children.subList(count, children.size()); children = children.subList(count, children.size());
} }
public void trimChildrenRight(int count) {
children = children.subList(0, children.size() - count);
}
public TreeConnectionType getConnectionType() { public TreeConnectionType getConnectionType() {
return connectionType; return connectionType;
} }
@@ -92,7 +92,10 @@ public class TreeLeaf implements ITree {
@Override @Override
public String toString() { 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() { public String toHTML() {
Binary file not shown.
@@ -130,6 +130,7 @@ public abstract class AbstractLeadedComponent<T> extends AbstractTransparentComp
: borderColor; : borderColor;
} }
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1f));
g2d.setColor(finalBorderColor); g2d.setColor(finalBorderColor);
g2d.draw(body); g2d.draw(body);
if (!outlineMode) { if (!outlineMode) {
@@ -1,49 +1,55 @@
/* /*
*
DIY Layout Creator (DIYLC). * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
Copyright (c) 2009-2018 held jointly by the individual authors. *
* This file is part of DIYLC.
This file is part of DIYLC. *
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
DIYLC is free software: you can redistribute it and/or modify * General Public License as published by the Free Software Foundation, either version 3 of the
it under the terms of the GNU General Public License as published by * License, or (at your option) any later version.
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
DIYLC is distributed in the hope that it will be useful, * Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * You should have received a copy of the GNU General Public License along with DIYLC. If not, see
GNU General Public License for more details. * <http://www.gnu.org/licenses/>.
*/
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc.netlist; package org.diylc.netlist;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
public abstract class AbstractNetlistAnalyzer { public abstract class AbstractNetlistAnalyzer {
public AbstractNetlistAnalyzer() { 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<Node>());
// 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<Node>());
// System.out.println(tree1);
protected Tree constructTree(Netlist netlist, Node nodeA, Node nodeB) {
Tree tree = new Tree(new ArrayList<Tree>(), TreeConnectionType.Parallel);
connectNodes(netlist, nodeA, nodeB, tree.getChildren(), null, new HashSet<Node>());
// System.out.println(netlist.getSwitchSetup());
// System.out.println(tree);
return tree; return tree;
} }
protected void connectNodes(Netlist netlist, Node nodeA, Node nodeB, List<Tree> concurrentPaths, Tree currentPath, Set<Node> visited) { protected void connectNodes(Netlist netlist, Node nodeA, Node nodeB, List<Tree> concurrentPaths, Tree currentPath,
Set<Node> visited) {
if (nodeA == nodeB) { if (nodeA == nodeB) {
concurrentPaths.add(currentPath); concurrentPaths.add(currentPath);
return; return;
@@ -59,7 +65,9 @@ public abstract class AbstractNetlistAnalyzer {
return; return;
} }
visited.add(nodeA); visited.addAll(groupA.getNodes());
List<Tree> newConcurrentPaths = new ArrayList<Tree>();
for (Node n : groupA.getNodes()) { for (Node n : groupA.getNodes()) {
IDIYComponent<?> c = n.getComponent(); IDIYComponent<?> c = n.getComponent();
@@ -68,65 +76,138 @@ public abstract class AbstractNetlistAnalyzer {
TreeLeaf l = new TreeLeaf(c, i, n.getPointIndex()); TreeLeaf l = new TreeLeaf(c, i, n.getPointIndex());
Node newNodeA = new Node(c, i); Node newNodeA = new Node(c, i);
if (!visited.contains(newNodeA)) { if (!visited.contains(newNodeA)) {
visited.add(n); // visited.add(n);
Tree newCurrentPath = null; Tree newCurrentPath = null;
try { try {
if (currentPath == null)
newCurrentPath = new Tree(new ArrayList<Tree>(), TreeConnectionType.Series);
else
newCurrentPath = (Tree) currentPath.clone(); newCurrentPath = (Tree) currentPath.clone();
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
} }
Tree newItem = new Tree(l); Tree newItem = new Tree(l);
if (!newCurrentPath.getChildren().contains(newItem)) if (!newCurrentPath.getChildren().contains(newItem))
newCurrentPath.getChildren().add(newItem); newCurrentPath.getChildren().add(newItem);
// if (!currentPath.contains(l)) // if (!currentPath.contains(l))
// newCurrentPath.add(l); // newCurrentPath.add(l);
Set<Node> newVisited = new HashSet<Node>(visited); Set<Node> newVisited = new HashSet<Node>(visited);
connectNodes(netlist, newNodeA, nodeB, concurrentPaths, newCurrentPath, newVisited); connectNodes(netlist, newNodeA, nodeB, newConcurrentPaths, newCurrentPath, newVisited);
} }
} }
} }
} }
if (concurrentPaths.size() < 2) if (newConcurrentPaths.size() == 0)
return; return;
Tree jointSection = new Tree(new ArrayList<Tree>(), TreeConnectionType.Series);
for (int i = 0; i < concurrentPaths.get(0).getChildren().size(); i++) { if (newConcurrentPaths.size() == 1) {
Tree unique = concurrentPaths.get(0).getChildren().get(i); 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<Tree> paths, boolean backward) {
Map<Tree, Integer> uniques = new HashMap<Tree, Integer>();
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);
}
List<Tree> unmerged = new ArrayList<Tree>(paths);
for (Map.Entry<Tree, Integer> e : uniques.entrySet()) {
if (e.getValue() > 1) {
List<Tree> pathsToMerge = new ArrayList<Tree>();
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<Tree>(), TreeConnectionType.Series);
Tree jointFinish = new Tree(new ArrayList<Tree>(), TreeConnectionType.Series);
Tree unique = e.getKey();
for (int i = 0; i < pathsToMerge.get(0).getChildren().size(); i++) {
boolean canMerge = true; boolean canMerge = true;
for (Tree t : concurrentPaths) { unique = pathsToMerge.get(0).getChildren().get(backward ? pathsToMerge.get(0).getChildren().size() - i - 1 : i);
if (t.getConnectionType() != TreeConnectionType.Series || t.getChildren().size() <= i || !t.getChildren().get(i).equals(unique)) { for (Tree t : pathsToMerge) {
if (t.getChildren().size() <= i || !t.getChildren().get(backward ? t.getChildren().size() - i - 1 : i).equals(unique)) {
canMerge = false; canMerge = false;
break; break;
} }
} }
if (canMerge) if (canMerge)
jointSection.getChildren().add(unique); (backward ? jointFinish : jointStart).getChildren().add(unique);
else else
break; break;
} }
if (!jointSection.getChildren().isEmpty()) {
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<Tree>(), TreeConnectionType.Series); Tree mergedTree = new Tree(new ArrayList<Tree>(), TreeConnectionType.Series);
mergedTree.getChildren().add(jointSection); Tree parallelSection = new Tree(new ArrayList<Tree>(pathsToMerge), TreeConnectionType.Parallel);
Tree parallelSection = new Tree(new ArrayList<Tree>(concurrentPaths), TreeConnectionType.Parallel); if (!jointStart.getChildren().isEmpty()) {
mergedTree.getChildren().add(jointStart);
for (Tree t : parallelSection.getChildren()) { for (Tree t : parallelSection.getChildren()) {
t.trimChildren(jointSection.getChildren().size()); t.trimChildrenLeft(jointStart.getChildren().size());
}
} }
mergedTree.getChildren().add(parallelSection); mergedTree.getChildren().add(parallelSection);
concurrentPaths.clear(); if (!jointFinish.getChildren().isEmpty()) {
concurrentPaths.add(mergedTree); mergedTree.getChildren().add(jointFinish);
for (Tree t : parallelSection.getChildren()) {
t.trimChildrenRight(jointFinish.getChildren().size());
}
}
paths.removeAll(pathsToMerge);
paths.add(mergedTree);
}
} }
} }
protected void findAllPaths(Netlist netlist, Node nodeA, Node nodeB, List<TreeLeaf> currentPath, List<List<TreeLeaf>> allPaths, Set<Node> visited) { // 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<TreeLeaf> currentPath,
List<List<TreeLeaf>> allPaths, Set<Node> visited) {
if (nodeA == nodeB) { if (nodeA == nodeB) {
allPaths.add(currentPath); allPaths.add(currentPath);
return; return;
} }
// System.out.println("Finding path between " + nodeA + " and " + nodeB); // System.out.println("Finding path between " + nodeA + " and " + nodeB);
Group groupA = findGroup(netlist, nodeA); Group groupA = findGroup(netlist, nodeA);
@@ -169,8 +250,8 @@ public abstract class AbstractNetlistAnalyzer {
List<Group> res = new ArrayList<Group>(); List<Group> res = new ArrayList<Group>();
for (Group g : netlist.getGroups()) { for (Group g : netlist.getGroups()) {
for (Node n : g.getNodes()) { for (Node n : g.getNodes()) {
if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) && if (typeNames.contains(n.getComponent().getClass().getCanonicalName())
(nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
res.add(g); res.add(g);
break; break;
} }
@@ -183,8 +264,8 @@ public abstract class AbstractNetlistAnalyzer {
List<Node> res = new ArrayList<Node>(); List<Node> res = new ArrayList<Node>();
for (Node n : group.getNodes()) { for (Node n : group.getNodes()) {
if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) && if (typeNames.contains(n.getComponent().getClass().getCanonicalName())
(nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
res.add(n); res.add(n);
} }
} }
@@ -196,8 +277,8 @@ public abstract class AbstractNetlistAnalyzer {
List<Group> res = new ArrayList<Group>(); List<Group> res = new ArrayList<Group>();
for (Group g : netlist.getGroups()) { for (Group g : netlist.getGroups()) {
for (Node n : g.getNodes()) { for (Node n : g.getNodes()) {
if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) && if (typeNames.contains(n.getComponent().getClass().getCanonicalName())
(nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
res.add(g); res.add(g);
break; break;
} }
@@ -206,13 +287,14 @@ public abstract class AbstractNetlistAnalyzer {
return res; return res;
} }
protected List<Group> findGroups(Set<String> typeNames, String nodeName, Netlist netlist, Collection<IDIYComponent<?>> belongTo) { protected List<Group> findGroups(Set<String> typeNames, String nodeName, Netlist netlist,
Collection<IDIYComponent<?>> belongTo) {
List<Group> res = new ArrayList<Group>(); List<Group> res = new ArrayList<Group>();
for (Group g : netlist.getGroups()) { for (Group g : netlist.getGroups()) {
for (Node n : g.getNodes()) { for (Node n : g.getNodes()) {
if ((belongTo == null || belongTo.contains(n.getComponent())) && if ((belongTo == null || belongTo.contains(n.getComponent()))
(typeNames.contains(n.getComponent().getClass().getCanonicalName())) && && (typeNames.contains(n.getComponent().getClass().getCanonicalName()))
(nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
res.add(g); res.add(g);
break; break;
} }
@@ -225,8 +307,8 @@ public abstract class AbstractNetlistAnalyzer {
List<Node> res = new ArrayList<Node>(); List<Node> res = new ArrayList<Node>();
for (Group g : netlist.getGroups()) { for (Group g : netlist.getGroups()) {
for (Node n : g.getNodes()) { for (Node n : g.getNodes()) {
if (typeNames.contains(n.getComponent().getClass().getCanonicalName()) && if (typeNames.contains(n.getComponent().getClass().getCanonicalName())
(nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
res.add(n); res.add(n);
} }
} }
@@ -251,8 +333,8 @@ public abstract class AbstractNetlistAnalyzer {
} }
for (Node n : g.getNodes()) { for (Node n : g.getNodes()) {
if (inGroup && typeNames.contains(n.getComponent().getClass().getCanonicalName()) && if (inGroup && typeNames.contains(n.getComponent().getClass().getCanonicalName())
(nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { && (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
res.add(n); res.add(n);
} }
} }
@@ -260,13 +342,15 @@ public abstract class AbstractNetlistAnalyzer {
return res; return res;
} }
protected List<Node> find(Set<String> typeNames, String nodeName, Netlist netlist, Collection<IDIYComponent<?>> belongTo) { protected List<Node> find(Set<String> typeNames, String nodeName, Netlist netlist,
Collection<IDIYComponent<?>> belongTo) {
List<Node> res = new ArrayList<Node>(); List<Node> res = new ArrayList<Node>();
for (Group g : netlist.getGroups()) { for (Group g : netlist.getGroups()) {
for (Node n : g.getNodes()) { for (Node n : g.getNodes()) {
if ((belongTo == null || belongTo.contains(n.getComponent())) && typeNames.contains(n.getComponent().getClass().getCanonicalName()) && if ((belongTo == null || belongTo.contains(n.getComponent()))
(nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) { && typeNames.contains(n.getComponent().getClass().getCanonicalName())
&& (nodeName == null || n.getDisplayName().equalsIgnoreCase(nodeName))) {
res.add(n); res.add(n);
} }
} }
@@ -164,7 +164,7 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
} else { } else {
Node jackTip = jackTipNodes.get(0); Node jackTip = jackTipNodes.get(0);
Node jackSleeve = jackSleeveNodes.get(0); Node jackSleeve = jackSleeveNodes.get(0);
return constructTree(netlist, jackTip, jackSleeve); return constructTreeBetween(netlist, jackTip, jackSleeve);
} }
} }
} }
Binary file not shown.
Binary file not shown.