Circuit analysis algorithm that supports netlist extraction, 'Highlight connected Areas' and 'Guitar Wiring Analyzer' features improved to take PCB trace layer and component z-order into account for better accuracy

This commit is contained in:
Bane Stojkovic
2022-11-23 22:50:01 +01:00
parent ec5e1ae233
commit d3d98b3058
28 changed files with 447 additions and 160 deletions
@@ -23,9 +23,13 @@ package org.diylc.common;
public enum PCBLayer {
_1, _2, _3, _4, _5;
_1, _2, _3, _4, _5, _6, _7, _8;
public String toString() {
return name().substring(1);
};
};
public int getId() {
return Integer.parseInt(toString());
}
}
@@ -0,0 +1,53 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
package org.diylc.core;
/**
* Component with all extra info for it to be rendered on the screen.
*
* @author Branislav Stojkovic
*/
public class ComponentForRender {
private IDIYComponent<?> component;
private ComponentState state;
private int zOrder;
public ComponentForRender(IDIYComponent<?> component, ComponentState state, int zOrder) {
super();
this.component = component;
this.state = state;
this.zOrder = zOrder;
}
public IDIYComponent<?> getComponent() {
return component;
}
public ComponentState getState() {
return state;
}
public int getZOrder() {
return zOrder;
}
}
@@ -0,0 +1,6 @@
package org.diylc.core;
public interface ILayer {
int getLayerId();
}
@@ -23,6 +23,8 @@ import java.awt.geom.Point2D;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.diylc.presenter.ContinuityArea;
import org.diylc.utils.RTree;
/***
@@ -34,9 +36,9 @@ import org.diylc.utils.RTree;
public class ContinuityGraph {
private RTree<ContinuityNode> groupTree;
private Map<Integer, List<Area>> areaGroupMap;
private Map<Integer, List<ContinuityArea>> areaGroupMap;
public ContinuityGraph(RTree<ContinuityNode> groupTree, Map<Integer, List<Area>> areaGroupMap) {
public ContinuityGraph(RTree<ContinuityNode> groupTree, Map<Integer, List<ContinuityArea>> areaGroupMap) {
super();
this.groupTree = groupTree;
this.areaGroupMap = areaGroupMap;
@@ -44,22 +46,26 @@ public class ContinuityGraph {
public List<Area> findAreasFor(Point2D point) {
Optional<ContinuityNode> first = groupTree.search(point, NetlistBuilder.eps).stream()
.filter(node -> node.getArea().contains(point)).findFirst();
.filter(node -> node.getArea().getArea().contains(point)).findFirst();
return first.map(node -> areaGroupMap.get(node.getGroupId())).orElse(null);
return first.map(node ->
areaGroupMap.get(node.getGroupId())
.stream()
.map(x -> x.getArea())
.collect(Collectors.toList())).orElse(null);
}
public static class ContinuityNode {
private Area area;
private ContinuityArea area;
private Integer groupId;
public ContinuityNode(Area area, Integer groupId) {
public ContinuityNode(ContinuityArea area, Integer groupId) {
super();
this.area = area;
this.groupId = groupId;
}
public Area getArea() {
public ContinuityArea getArea() {
return area;
}
@@ -52,7 +52,11 @@ public class Group implements Comparable<Group> {
}
public Group connect(IDIYComponent<?> component, int index) {
getNodes().add(new Node(component, index));
return connect(component, index, 0);
}
public Group connect(IDIYComponent<?> component, int index, int zOrder) {
getNodes().add(new Node(component, index, zOrder));
return this;
}
@@ -80,7 +80,7 @@ public abstract class NetlistAnalyzer {
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);
Node newNodeA = new Node(c, i, n.getZIndex());
if (!visited.contains(newNodeA)) {
// visited.add(n);
Tree newCurrentPath = null;
@@ -22,6 +22,7 @@ import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -39,6 +40,7 @@ import org.diylc.lang.LangUtil;
import org.diylc.netlist.ContinuityGraph.ContinuityNode;
import org.diylc.presenter.ComponentProcessor;
import org.diylc.presenter.Connection;
import org.diylc.presenter.ContinuityArea;
import org.diylc.utils.RTree;
import com.google.common.graph.GraphBuilder;
import com.google.common.graph.ImmutableGraph;
@@ -55,36 +57,39 @@ public class NetlistBuilder {
.translate("Maximum number of switching combinations exceeded. Allowed: %s, actual: %s");
@SuppressWarnings("unchecked")
public static List<Netlist> extractNetlists(boolean includeSwitches, Project project, List<Area> continuityAreas)
throws NetlistException {
public static List<Netlist> extractNetlists(boolean includeSwitches, Project project,
List<ContinuityArea> continuityAreas) throws NetlistException {
Map<Netlist, Netlist> result = new HashMap<Netlist, Netlist>();
List<Node> nodes = new ArrayList<Node>();
List<ISwitch> switches = new ArrayList<ISwitch>();
Set<String> commonNodes = new HashSet<String>();
for (IDIYComponent<?> c : project.getComponents()) {
for (int j = 0; j < project.getComponents().size(); j++) {
IDIYComponent<?> c = project.getComponents().get(j);
ComponentType type = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
// extract nodes
if (!(c instanceof IContinuity) && !(c instanceof ICommonNode)) {
// regular components, create a node per control point
for (int i = 0; i < c.getControlPointCount(); i++) {
String nodeName = c.getControlPointNodeName(i);
if (nodeName != null
if (c.isControlPointSticky(i) && nodeName != null
&& (!includeSwitches || !ISwitch.class.isAssignableFrom(type.getInstanceClass()))) {
nodes.add(new Node(c, i));
nodes.add(new Node(c, i, j));
}
}
}
// create only one node per common label to avoid duplications in the netlist, as they will get eventually connected anyways
// create only one node per common label to avoid duplications in the netlist, as they will
// get eventually connected anyways
if (c instanceof ICommonNode) {
String label = ((ICommonNode)c).getCommonNodeLabel();
String label = ((ICommonNode) c).getCommonNodeLabel();
if (!commonNodes.contains(label)) {
commonNodes.add(label);
nodes.add(new Node(c, 0));
nodes.add(new Node(c, 0, j));
}
}
@@ -142,8 +147,8 @@ public class NetlistBuilder {
}
List<Connection> connections = getConnections(project, switchPositions);
Netlist netlist = NetlistBuilder.buildNetlist(project.getComponents(), nodes,
continuityAreas, connections);
Netlist netlist =
NetlistBuilder.buildNetlist(project.getComponents(), nodes, continuityAreas, connections);
// merge graphs that are effectively the same
if (result.containsKey(netlist)) {
@@ -176,7 +181,7 @@ public class NetlistBuilder {
}
public static Netlist buildNetlist(List<IDIYComponent<?>> components, Collection<Node> nodes,
Collection<Area> continuityAreas, Collection<Connection> connections) {
Collection<ContinuityArea> continuityAreas, Collection<Connection> connections) {
ImmutableGraph<ProjectGraphNode> graph = buildGraph(nodes, continuityAreas, connections);
Traverser<ProjectGraphNode> traverser = Traverser.forGraph(graph);
@@ -211,7 +216,7 @@ public class NetlistBuilder {
return netlist;
}
public static ContinuityGraph buildContinuityGraph(Collection<Area> continuityAreas,
public static ContinuityGraph buildContinuityGraph(Collection<ContinuityArea> continuityAreas,
Collection<Connection> connections) {
ImmutableGraph<ProjectGraphNode> graph =
buildGraph(new ArrayList<Node>(), continuityAreas, connections);
@@ -224,7 +229,7 @@ public class NetlistBuilder {
int groupId = 1;
RTree<ContinuityNode> groupTree = new RTree<ContinuityGraph.ContinuityNode>();
Map<Integer, List<Area>> areaGroupMap = new HashMap<Integer, List<Area>>();
Map<Integer, List<ContinuityArea>> areaGroupMap = new HashMap<Integer, List<ContinuityArea>>();
while (true) {
@@ -237,12 +242,13 @@ public class NetlistBuilder {
final int finalGroupId = groupId;
List<Area> areaList = new ArrayList<Area>();
List<ContinuityArea> areaList = new ArrayList<ContinuityArea>();
traverser.breadthFirst(nodeArr[i]).forEach(node -> {
visited.add(node);
if (node.getArea() != null) {
areaList.add(node.getArea());
groupTree.insert(node.getArea(), new ContinuityNode(node.getArea(), finalGroupId));
groupTree.insert(node.getArea().getArea(),
new ContinuityNode(node.getArea(), finalGroupId));
}
});
@@ -257,7 +263,7 @@ public class NetlistBuilder {
/****
* Build an {@link ImmutableGraph} containing the following nodes: project nodes, both ends of
* each connection and one node per continuity areas. All vertices are added based on object
* each connection and one node per continuity area. All vertices are added based on object
* proximity or intersection.
*
* @param nodes
@@ -266,45 +272,52 @@ public class NetlistBuilder {
* @return
*/
private static ImmutableGraph<ProjectGraphNode> buildGraph(Collection<Node> nodes,
Collection<Area> continuityAreas, Collection<Connection> connections) {
Map<Point2D, List<ProjectGraphNode>> nodeMap = new HashMap<Point2D, List<ProjectGraphNode>>();
Collection<ContinuityArea> continuityAreas, Collection<Connection> connections) {
RTree<ProjectGraphNode> nodeTree = new RTree<ProjectGraphNode>();
Map<Point2D, List<ProjectGraphNode>> nodeMapByPoint =
new HashMap<Point2D, List<ProjectGraphNode>>();
// RTree<ProjectGraphNode> nodeTree = new RTree<ProjectGraphNode>();
RTree<ProjectGraphNode> areaTree = new RTree<ProjectGraphNode>();
Builder<ProjectGraphNode> builder = GraphBuilder.undirected().<ProjectGraphNode>immutable();
List<ProjectGraphNode> controlPointNodeList = new ArrayList<ProjectGraphNode>();
for (Node node : nodes) {
Point2D p = snapToEps(node.getPoint2D(), eps);
ProjectGraphNode graphNode = new ProjectGraphNode(p, node);
builder.addNode(graphNode);
nodeTree.insert(new float[] {(float) (p.getX() - eps), (float) (p.getY() - eps)},
new float[] {eps * 2, eps * 2}, graphNode);
nodeMap.computeIfAbsent(p, (point) -> new ArrayList<ProjectGraphNode>())
// nodeTree.insert(new float[] {(float) (p.getX() - eps), (float) (p.getY() - eps)},
// new float[] {eps * 2, eps * 2}, graphNode);
nodeMapByPoint.computeIfAbsent(p, (point) -> new ArrayList<ProjectGraphNode>())
.add(new ProjectGraphNode(p, node));
controlPointNodeList.add(graphNode);
}
for (Connection conn : connections) {
Point2D p1 = snapToEps(conn.getP1(), eps);
Point2D p2 = snapToEps(conn.getP2(), eps);
ProjectGraphNode graphNode1 = new ProjectGraphNode(p1);
ProjectGraphNode graphNode2 = new ProjectGraphNode(p2);
ProjectGraphNode graphNode1 = new ProjectGraphNode(p1, conn.getZIndex());
ProjectGraphNode graphNode2 = new ProjectGraphNode(p2, conn.getZIndex());
nodeTree.insert(new float[] {(float) p1.getX() - eps, (float) p1.getY() - eps},
new float[] {eps * 2, eps * 2}, graphNode1);
nodeTree.insert(new float[] {(float) p2.getX() - eps, (float) p2.getY() - eps},
new float[] {eps * 2, eps * 2}, graphNode2);
// nodeTree.insert(new float[] {(float) p1.getX() - eps, (float) p1.getY() - eps},
// new float[] {eps * 2, eps * 2}, graphNode1);
// nodeTree.insert(new float[] {(float) p2.getX() - eps, (float) p2.getY() - eps},
// new float[] {eps * 2, eps * 2}, graphNode2);
builder.addNode(graphNode1);
builder.addNode(graphNode2);
builder.putEdge(graphNode1, graphNode2);
nodeMap.computeIfAbsent(p1, (point) -> new ArrayList<ProjectGraphNode>()).add(graphNode1);
nodeMap.computeIfAbsent(p2, (point) -> new ArrayList<ProjectGraphNode>()).add(graphNode2);
nodeMapByPoint.computeIfAbsent(p1, (point) -> new ArrayList<ProjectGraphNode>())
.add(graphNode1);
nodeMapByPoint.computeIfAbsent(p2, (point) -> new ArrayList<ProjectGraphNode>())
.add(graphNode2);
}
for (Map.Entry<Point2D, List<ProjectGraphNode>> entry : nodeMap.entrySet()) {
for (Map.Entry<Point2D, List<ProjectGraphNode>> entry : nodeMapByPoint.entrySet()) {
ProjectGraphNode[] nodeArr = entry.getValue().toArray(new ProjectGraphNode[0]);
for (int i = 0; i < nodeArr.length - 1; i++) {
for (int j = i + 1; j < nodeArr.length; j++) {
@@ -313,30 +326,36 @@ public class NetlistBuilder {
}
}
for (Area area : continuityAreas) {
for (ContinuityArea area : continuityAreas) {
ProjectGraphNode areaNode = new ProjectGraphNode(area);
builder.addNode(areaNode);
ProjectGraphNode[] nodeArr = nodeTree.search(area).stream()
.filter(graphNode -> area.contains(graphNode.getPoint())
|| area.intersects(graphNode.getPoint().getX() - eps / 2,
graphNode.getPoint().getY() - eps / 2, eps, eps))
.collect(Collectors.toList()).toArray(new ProjectGraphNode[0]);
// List<ProjectGraphNode> candidateNodes = nodeTree.search(area.getArea()).stream()
// .filter(graphNode -> area.getArea().contains(graphNode.getPoint())
// || area.getArea().intersects(graphNode.getPoint().getX() - eps / 2,
// graphNode.getPoint().getY() - eps / 2, eps, eps))
// .collect(Collectors.toList());
//
// List<ProjectGraphNode> nodesAbove = candidateNodes.stream()
// .filter(x -> x.getNode().getZIndex() > area.getZOrder())
// .sorted(Comparator.comparing(x -> x.getNode().getZIndex(), Comparator.reverseOrder()))
// .collect(Collectors.toList());
//
// for (ProjectGraphNode node : nodeArr) {
// builder.putEdge(node, areaNode);
// }
for (ProjectGraphNode node : nodeArr) {
builder.putEdge(node, areaNode);
}
// for (int i = 0; i < nodeArr.length - 1; i++) {
// for (int j = i + 1; j < nodeArr.length; j++) {
// builder.putEdge(nodeArr[i], nodeArr[j]);
// }
// }
for (int i = 0; i < nodeArr.length - 1; i++) {
for (int j = i + 1; j < nodeArr.length; j++) {
builder.putEdge(nodeArr[i], nodeArr[j]);
}
}
areaTree.search(area).stream().filter(graphNode -> {
if (graphNode.getArea() != null && graphNode.getArea() != area) {
Area a = new Area(graphNode.getArea());
a.intersect(area);
areaTree.search(area.getArea()).stream().filter(graphNode -> {
if (graphNode.getArea() != null && graphNode.getArea() != area
&& graphNode.getArea().getLayerId() == area.getLayerId()) {
Area a = new Area(graphNode.getArea().getArea());
a.intersect(area.getArea());
return !a.isEmpty();
}
return false;
@@ -344,36 +363,68 @@ public class NetlistBuilder {
builder.putEdge(graphNode, areaNode);
});
areaTree.insert(area, areaNode);
areaTree.insert(area.getArea(), areaNode);
}
for (Map.Entry<Point2D, List<ProjectGraphNode>> entry : nodeMapByPoint.entrySet()) {
final Point2D point = entry.getKey();
List<ProjectGraphNode> candidateAreaNodes = areaTree.search(point, eps).stream()
.filter(graphNode -> graphNode.getArea().getArea().contains(point)
|| graphNode.getArea().getArea().intersects(point.getX() - eps / 2,
point.getY() - eps / 2, eps, eps))
.collect(Collectors.toList());
if (candidateAreaNodes.isEmpty())
continue;
for (ProjectGraphNode pointNode : entry.getValue()) {
List<ProjectGraphNode> areaNodesBelowPoint = candidateAreaNodes.stream()
.filter(x -> x.getArea().getZIndex() < pointNode.getZIndex())
.sorted(Comparator.comparing(x -> x.getArea().getZIndex(), Comparator.reverseOrder()))
.collect(Collectors.toList());
if (areaNodesBelowPoint.isEmpty()) {
builder.putEdge(pointNode, candidateAreaNodes.get(0));
} else {
builder.putEdge(pointNode, areaNodesBelowPoint.get(0));
}
}
}
return builder.build();
}
@SuppressWarnings({"unchecked", "unlikely-arg-type"})
private static List<Connection> getConnections(Project project, Map<ISwitch, Integer> switchPositions) {
private static List<Connection> getConnections(Project project,
Map<ISwitch, Integer> switchPositions) {
Set<Connection> connections = new TreeSet<Connection>();
Map<String, List<IDIYComponent<?>>> commonNodeMap = new HashMap<String, List<IDIYComponent<?>>>();
for (IDIYComponent<?> c : project.getComponents()) {
ComponentType type =
ComponentProcessor.getInstance().extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
Map<String, List<IDIYComponent<?>>> commonNodeMap =
new HashMap<String, List<IDIYComponent<?>>>();
for (int z = 0; z < project.getComponents().size(); z++) {
IDIYComponent<?> c = project.getComponents().get(z);
ComponentType type = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
// handle direct connections
if (c instanceof IContinuity) {
for (int i = 0; i < c.getControlPointCount() - 1; i++)
for (int j = i + 1; j < c.getControlPointCount(); j++)
if (((IContinuity) c).arePointsConnected(i, j))
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j)));
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j), z));
}
// handle switches
if (ISwitch.class.isAssignableFrom(type.getInstanceClass()) && switchPositions.containsKey(c)) {
if (ISwitch.class.isAssignableFrom(type.getInstanceClass())
&& switchPositions.containsKey(c)) {
int position = switchPositions.get(c);
ISwitch s = (ISwitch) c;
for (int i = 0; i < c.getControlPointCount() - 1; i++)
for (int j = i + 1; j < c.getControlPointCount(); j++)
if (s.arePointsConnected(i, j, position))
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j)));
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j), z));
}
// handle common nodes
if (ICommonNode.class.isAssignableFrom(type.getInstanceClass())) {
@@ -382,12 +433,13 @@ public class NetlistBuilder {
commonNodeMap.computeIfAbsent(label, (key) -> new ArrayList<IDIYComponent<?>>()).add(c);
}
}
// connect common nodes together by chaining them one by one
for (List<IDIYComponent<?>> commonPoints : commonNodeMap.values()) {
IDIYComponent<?>[] commonPointArr = commonPoints.toArray(new IDIYComponent<?>[0]);
for (int i = 0; i < commonPointArr.length - 1; i++) {
connections.add(new Connection(commonPointArr[i].getControlPoint(0), commonPointArr[i + 1].getControlPoint(0)));
connections.add(new Connection(commonPointArr[i].getControlPoint(0),
commonPointArr[i + 1].getControlPoint(0), 0));
}
}
@@ -399,19 +451,22 @@ public class NetlistBuilder {
Math.round(point.getY() / eps) * eps);
}
private static class ProjectGraphNode {
static class ProjectGraphNode {
private Point2D point;
private Node node;
private Area area;
private ContinuityArea area;
private int zIndex;
public ProjectGraphNode(Area area) {
public ProjectGraphNode(ContinuityArea area) {
super();
this.area = area;
this.zIndex = area.getZIndex();
}
public ProjectGraphNode(Point2D point) {
public ProjectGraphNode(Point2D point, int zIndex) {
super();
this.point = point;
this.zIndex = zIndex;
this.node = null;
}
@@ -419,17 +474,22 @@ public class NetlistBuilder {
super();
this.point = point;
this.node = node;
this.zIndex = node.getZIndex();
}
public Point2D getPoint() {
return point;
}
public int getZIndex() {
return zIndex;
}
public Node getNode() {
return node;
}
public Area getArea() {
public ContinuityArea getArea() {
return area;
}
}
@@ -34,11 +34,13 @@ public class Node implements Comparable<Node> {
private IDIYComponent<?> component;
private int pointIndex;
private int zIndex;
public Node(IDIYComponent<?> component, int pointIndex) {
public Node(IDIYComponent<?> component, int pointIndex, int zIndex) {
super();
this.component = component;
this.pointIndex = pointIndex;
this.zIndex = zIndex;
}
public IDIYComponent<?> getComponent() {
@@ -49,6 +51,10 @@ public class Node implements Comparable<Node> {
return pointIndex;
}
public int getZIndex() {
return zIndex;
}
public String getDisplayName() {
String[] section = component.getSectionNames(pointIndex);
return (section == null || section.length > 1 ? "" : section[0] + ".") + component.getControlPointNodeName(pointIndex);
@@ -29,6 +29,7 @@ public class ComponentArea implements Serializable {
private static final long serialVersionUID = 1L;
private int zOrder;
private Area outlineArea;
private Collection<Area> continuityPositiveAreas;
private Collection<Area> continuityNegativeAreas;
@@ -36,12 +37,17 @@ public class ComponentArea implements Serializable {
public ComponentArea() {
}
public ComponentArea(Area outlineArea, Collection<Area> continuityPositiveAreas, Collection<Area> continuityNegativeAreas) {
public ComponentArea(int zOrder, Area outlineArea, Collection<Area> continuityPositiveAreas, Collection<Area> continuityNegativeAreas) {
super();
this.zOrder = zOrder;
this.outlineArea = outlineArea;
this.continuityPositiveAreas = continuityPositiveAreas;
this.continuityNegativeAreas = continuityNegativeAreas;
}
public int getZOrder() {
return zOrder;
}
public Area getOutlineArea() {
return outlineArea;
@@ -28,10 +28,12 @@ public class Connection implements Comparable<Connection> {
private Point2D p1;
private Point2D p2;
private int zIndex;
public Connection(Point2D p1, Point2D p2) {
public Connection(Point2D p1, Point2D p2, int zIndex) {
this.p1 = p1.getX() < p2.getX() || p1.getX() == p2.getX() && p1.getY() < p2.getY() ? p1 : p2;
this.p2 = p1.getX() < p2.getX() || p1.getX() == p2.getX() && p1.getY() < p2.getY() ? p2 : p1;
this.zIndex = zIndex;
}
public Point2D getP1() {
@@ -41,6 +43,10 @@ public class Connection implements Comparable<Connection> {
public Point2D getP2() {
return p2;
}
public int getZIndex() {
return zIndex;
}
@Override
public int hashCode() {
@@ -48,6 +54,7 @@ public class Connection implements Comparable<Connection> {
int result = 1;
result = prime * result + ((p1 == null) ? 0 : p1.hashCode());
result = prime * result + ((p2 == null) ? 0 : p2.hashCode());
result = prime * result + zIndex;
return result;
}
@@ -70,6 +77,8 @@ public class Connection implements Comparable<Connection> {
return false;
} else if (!p2.equals(other.p2))
return false;
if (zIndex != other.zIndex)
return false;
return true;
}
@@ -0,0 +1,52 @@
/*
*
* 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
* <http://www.gnu.org/licenses/>.
*
*/
package org.diylc.presenter;
import java.awt.geom.Area;
import java.io.Serializable;
public class ContinuityArea implements Serializable {
private static final long serialVersionUID = 1L;
private int zIndex;
private int layerId;
private Area area;
public ContinuityArea() {}
public ContinuityArea(int zIndex, int layerId, Area area) {
super();
this.zIndex = zIndex;
this.layerId = layerId;
this.area = area;
}
public int getZIndex() {
return zIndex;
}
public Area getArea() {
return area;
}
public int getLayerId() {
return layerId;
}
}
@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.stream.Collectors;
import org.apache.log4j.Logger;
import org.diylc.common.ComponentType;
import org.diylc.core.ComponentForRender;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project;
@@ -63,14 +64,14 @@ public class DrawingCache {
* @param zoom
*/
@SuppressWarnings("unchecked")
public void bulkPrepare(Map<IDIYComponent<?>, ComponentState> components, G2DWrapper g2d, boolean outlineMode, Project project, double zoom) {
public void bulkPrepare(Collection<ComponentForRender> components, G2DWrapper g2d, boolean outlineMode, Project project, double zoom) {
// run all renders in parallel to utilize all CPU cores
components.entrySet().stream().parallel().forEach(x -> {
components.stream().parallel().forEach(x -> {
ComponentType type = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) x.getKey().getClass());
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) x.getComponent().getClass());
if (type != null && type.getEnableCache()) {
renderAndCache(x.getKey(), g2d, x.getValue(), outlineMode, project, zoom);
renderAndCache(x.getComponent(), g2d, x.getState(), outlineMode, project, zoom, x.getZOrder());
}
});
}
@@ -88,7 +89,7 @@ public class DrawingCache {
*/
@SuppressWarnings("unchecked")
public void draw(IDIYComponent<?> component, G2DWrapper g2d, ComponentState componentState,
boolean outlineMode, Project project, double zoom, Rectangle2D visibleRect) {
boolean outlineMode, Project project, double zoom, int zOrder, Rectangle2D visibleRect) {
ComponentType type = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass());
@@ -96,7 +97,7 @@ public class DrawingCache {
// if we need to apply caching
Point2D firstPoint = component.getControlPoint(0);
CacheValue value = renderAndCache(component, g2d, componentState, outlineMode, project, zoom);
CacheValue value = renderAndCache(component, g2d, componentState, outlineMode, project, zoom, zOrder);
if (value == null) {
return;
@@ -175,7 +176,7 @@ public class DrawingCache {
}
private CacheValue renderAndCache(IDIYComponent<?> component, G2DWrapper g2d, ComponentState componentState,
boolean outlineMode, Project project, double zoom) {
boolean outlineMode, Project project, double zoom, int zOrder) {
// if we need to apply caching
Point2D firstPoint = component.getControlPoint(0);
@@ -225,7 +226,7 @@ public class DrawingCache {
G2DWrapper wrapper = new G2DWrapper(cg2d, zoom);
// initialize wrapper
wrapper.startedDrawingComponent();
wrapper.startedDrawingComponent(zOrder);
long componentStart = System.nanoTime();
@@ -39,6 +39,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -52,9 +53,11 @@ import org.diylc.common.GridType;
import org.diylc.common.IComponentFilter;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache;
import org.diylc.core.ComponentForRender;
import org.diylc.core.ComponentState;
import org.diylc.core.IContinuity;
import org.diylc.core.IDIYComponent;
import org.diylc.core.ILayer;
import org.diylc.core.Project;
import org.diylc.core.Theme;
import org.diylc.core.VisibilityPolicy;
@@ -136,7 +139,7 @@ public class DrawingManager {
configManager.writeValue(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME);
}
componentAreaMap = new HashMap<IDIYComponent<?>, ComponentArea>();
componentAreaMap = new LinkedHashMap<IDIYComponent<?>, ComponentArea>();
lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS);
debugComponentAreas =
@@ -252,9 +255,10 @@ public class DrawingManager {
// g2dWrapper.resetTx();
// put components and their states in a map
Map<IDIYComponent<?>, ComponentState> componentStateMap =
new HashMap<IDIYComponent<?>, ComponentState>();
for (IDIYComponent<?> component : project.getComponents()) {
Map<IDIYComponent<?>, ComponentState> componentStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
List<ComponentForRender> componentForRenderList = new ArrayList<ComponentForRender>();
for (int i = 0; i < project.getComponents().size(); i++) {
IDIYComponent<?> component = project.getComponents().get(i);
ComponentState state = ComponentState.NORMAL;
if (drawOptions.contains(DrawOption.SELECTION) && selectedComponents.contains(component)) {
if (dragInProgress) {
@@ -264,17 +268,21 @@ public class DrawingManager {
}
}
componentStateMap.put(component, state);
componentForRenderList.add(new ComponentForRender(component, state, i));
}
boolean outlineMode = drawOptions.contains(DrawOption.OUTLINE_MODE);
// give the cache a chance to prepare all the components in multiple threads
if (drawOptions.contains(DrawOption.ENABLE_CACHING)) {
DrawingCache.Instance.bulkPrepare(componentStateMap, g2dWrapper, outlineMode, project, zoom);
DrawingCache.Instance.bulkPrepare(componentForRenderList, g2dWrapper, outlineMode, project, zoom);
}
// componentAreaMap.clear();
for (IDIYComponent<?> component : project.getComponents()) {
for (int i = 0; i < project.getComponents().size(); i++) {
IDIYComponent<?> component = project.getComponents().get(i);
// Do not draw the component if it's filtered out.
if (filter != null && !filter.testComponent(component)) {
continue;
@@ -285,7 +293,7 @@ public class DrawingManager {
boolean trackArea = lastDrawnStateMap.get(component) != state;
synchronized (g2d) {
g2dWrapper.startedDrawingComponent();
g2dWrapper.startedDrawingComponent(i);
if (!trackArea) {
g2dWrapper.stopTracking();
}
@@ -300,7 +308,7 @@ public class DrawingManager {
if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache
DrawingCache.Instance.draw(component, g2dWrapper, state,
drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, visibleRect);
drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, i, visibleRect);
else // go straight to the wrapper
component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
@@ -386,7 +394,7 @@ public class DrawingManager {
// Draw component slot in a separate composite.
if (componentSlot != null) {
g2dWrapper.startedDrawingComponent();
g2dWrapper.startedDrawingComponent(project.getComponents().size());
g2dWrapper.setComposite(slotComposite);
for (IDIYComponent<?> component : componentSlot) {
try {
@@ -684,77 +692,100 @@ public class DrawingManager {
messageDispatcher.dispatchMessage(EventType.REPAINT);
}
public void findContinuityAreaAtPoint(Project project, Point2D p) {
public void findContinuityAreaAtPoint(Point2D p) {
if (continuityGraphCache == null)
continuityGraphCache = getContinuityGraph(project);
continuityGraphCache = getContinuityGraph();
currentContinuityAreas = continuityGraphCache.findAreasFor(p);
}
public List<Area> getContinuityAreas(Project project) {
public List<ContinuityArea> getContinuityAreas() {
// Find all individual continuity areas for all components
List<Area> preliminaryAreas = new ArrayList<Area>();
List<ContinuityArea> preliminaryAreas = new ArrayList<ContinuityArea>();
List<Boolean> checkBreakout = new ArrayList<Boolean>();
for (IDIYComponent<?> c : project.getComponents()) {
ComponentArea a = getComponentArea(c);
for (Map.Entry<IDIYComponent<?>, ComponentArea> entry : this.componentAreaMap.entrySet()) {
ComponentArea a = entry.getValue();
if (a == null || a.getOutlineArea() == null)
continue;
IDIYComponent<?> component = entry.getKey();
int layerId;
if (component instanceof ILayer) {
layerId = ((ILayer)component).getLayerId();
} else {
layerId = component.hashCode();
}
Collection<Area> positiveAreas = a.getContinuityPositiveAreas();
if (positiveAreas != null)
if (positiveAreas != null) {
for (Area a1 : positiveAreas) {
preliminaryAreas.add(a1);
preliminaryAreas.add(new ContinuityArea(a.getZOrder(), layerId, a1));
checkBreakout.add(false);
}
}
Collection<Area> negativeAreas = a.getContinuityNegativeAreas();
if (negativeAreas != null) {
for (Area na : negativeAreas)
for (Area na : negativeAreas) {
for (int i = 0; i < preliminaryAreas.size(); i++) {
Area a1 = preliminaryAreas.get(i);
if (a1.intersects(na.getBounds2D())) {
a1.subtract(na);
ContinuityArea a1 = preliminaryAreas.get(i);
if (a1.getLayerId() == layerId && a1.getArea().intersects(na.getBounds2D())) {
a1.getArea().subtract(na);
checkBreakout.set(i, true);
}
}
}
}
}
// Check if we need to break some areas out in case they are interrupted
List<Area> areas = new ArrayList<Area>();
List<ContinuityArea> areas = new ArrayList<ContinuityArea>();
for (int i = 0; i < preliminaryAreas.size(); i++) {
Area a = preliminaryAreas.get(i);
if (checkBreakout.get(i))
areas.addAll(AreaUtils.tryAreaBreakout(a));
else
ContinuityArea a = preliminaryAreas.get(i);
if (checkBreakout.get(i)) {
List<Area> breakoutAreas = AreaUtils.tryAreaBreakout(a.getArea());
if (breakoutAreas.size() == 1) {
areas.add(a);
} else {
areas.addAll(breakoutAreas.stream()
.map(area -> new ContinuityArea(a.getZIndex(), a.getLayerId(), area))
.collect(Collectors.toList()));
}
} else
areas.add(a);
}
return areas;
}
public ContinuityGraph getContinuityGraph(Project project) {
public ContinuityGraph getContinuityGraph() {
Set<Connection> connections = new HashSet<Connection>();
for (IDIYComponent<?> c : project.getComponents()) {
int z = 0;
for (IDIYComponent<?> c : this.componentAreaMap.keySet()) {
if (c instanceof IContinuity) {
for (int i = 0; i < c.getControlPointCount() - 1; i++)
for (int j = i + 1; j < c.getControlPointCount(); j++)
if (((IContinuity) c).arePointsConnected(i, j))
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j)));
connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j), z));
}
z++;
}
List<Area> areas = getContinuityAreas(project);
List<ContinuityArea> areas = getContinuityAreas();
return NetlistBuilder.buildContinuityGraph(areas, connections);
}
public List<Area> getContinuityAreaProximity(Project project, float threshold) {
List<Area> continuityAreas = getContinuityAreas(project);
public List<Area> getContinuityAreaProximity(float threshold) {
List<ContinuityArea> continuityAreas = getContinuityAreas();
Stroke s = ObjectCache.getInstance().fetchBasicStroke(threshold - 1); // value eyeballed for
// approx good results
List<Area> expanded = continuityAreas.parallelStream()
.map((a) -> new Area(s.createStrokedShape(a))).collect(Collectors.toList());
.map((a) -> new Area(s.createStrokedShape(a.getArea()))).collect(Collectors.toList());
List<Area> intersections = new ArrayList<Area>();
for (int i = 0; i < expanded.size() - 1; i++) {
for (int j = i + 1; j < expanded.size(); j++) {
@@ -103,7 +103,8 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
private String continuityMarker;
private Shape lastShape;
private double zoom;
private double zoom;
private int zOrder;
/**
* Creates a wrapper around specified {@link Graphics2D} object.
@@ -127,22 +128,25 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
/**
* Clears out the current area and caches canvas settings.
*
* @param zOrder
*/
public void startedDrawingComponent() {
drawingComponent = true;
currentArea = new Area();
continuityPositiveAreas = new HashMap<String, Area>();
continuityNegativeAreas = new HashMap<String, Area>();
public void startedDrawingComponent(int zOrder) {
this.zOrder = zOrder;
this.drawingComponent = true;
this.currentArea = new Area();
this.continuityPositiveAreas = new HashMap<String, Area>();
this.continuityNegativeAreas = new HashMap<String, Area>();
// trackingStacks.clear();
continuityMarker = null;
originalStroke = canvasGraphics.getStroke();
originalColor = canvasGraphics.getColor();
originalTx = canvasGraphics.getTransform();
originalComposite = canvasGraphics.getComposite();
originalFont = canvasGraphics.getFont();
currentTx = new AffineTransform();
initialTx = canvasGraphics.getTransform();
lastShape = null;
this.continuityMarker = null;
this.originalStroke = canvasGraphics.getStroke();
this.originalColor = canvasGraphics.getColor();
this.originalTx = canvasGraphics.getTransform();
this.originalComposite = canvasGraphics.getComposite();
this.originalFont = canvasGraphics.getFont();
this.currentTx = new AffineTransform();
this.initialTx = canvasGraphics.getTransform();
this.lastShape = null;
startTracking();
}
@@ -159,7 +163,8 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
canvasGraphics.setComposite(originalComposite);
canvasGraphics.setFont(originalFont);
// Map<String, Integer> sorted = sortByComparator(trackingStacks, false);
return new ComponentArea(currentArea, new ArrayList<Area>(continuityPositiveAreas.values()), new ArrayList<Area>(continuityNegativeAreas.values()));
return new ComponentArea(zOrder,currentArea, new ArrayList<Area>(continuityPositiveAreas.values()),
new ArrayList<Area>(continuityNegativeAreas.values()));
}
// start - used for caching
@@ -680,7 +680,7 @@ public class Presenter implements IPlugInPort {
projectFileManager.notifyFileChange();
}
} else if (configManager.readBoolean(HIGHLIGHT_CONTINUITY_AREA, false) || altDown) {
drawingManager.findContinuityAreaAtPoint(currentProject, scaledPoint);
drawingManager.findContinuityAreaAtPoint(scaledPoint);
messageDispatcher.dispatchMessage(EventType.REPAINT);
} else {
List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(selectedComponents);
@@ -2809,7 +2809,7 @@ public class Presenter implements IPlugInPort {
@Override
public List<Netlist> extractNetlists(boolean includeSwitches) throws NetlistException {
List<Area> continuityAreas = drawingManager.getContinuityAreas(currentProject);
List<ContinuityArea> continuityAreas = drawingManager.getContinuityAreas();
return NetlistBuilder.extractNetlists(includeSwitches, currentProject, continuityAreas);
}
@@ -2874,11 +2874,12 @@ public class Presenter implements IPlugInPort {
ComponentArea componentArea = drawingManager.getComponentArea(c);
areas.put(c, componentArea);
}
return new Snapshot(currentProject.clone(), new HashSet<IDIYComponent<?>>(selectedComponents), areas, new HashSet<Area>(drawingManager.getContinuityAreas(currentProject)));
return new Snapshot(currentProject.clone(), new HashSet<IDIYComponent<?>>(selectedComponents), areas,
new HashSet<ContinuityArea>(drawingManager.getContinuityAreas()));
}
@Override
public List<Area> checkContinuityAreaProximity(Size threshold) {
return drawingManager.getContinuityAreaProximity(this.currentProject, (float)threshold.convertToPixels());
return drawingManager.getContinuityAreaProximity((float)threshold.convertToPixels());
}
}
@@ -4158,6 +4158,10 @@
<changeType>BUG_FIX</changeType>
<description>Fixed an issue that would cause capacitors to fail when creating, editing, moving or deleting</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Circuit analysis algorithm that supports netlist extraction, 'Highlight connected Areas' and 'Guitar Wiring Analyzer' features improved to take PCB trace layer and component z-order into account for better accuracy</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added standard models in the drop down menu of the component toolbar</description>
@@ -1,12 +1,12 @@
package org.diylc.test;
import java.awt.geom.Area;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Project;
import org.diylc.presenter.ComponentArea;
import org.diylc.presenter.ContinuityArea;
public class Snapshot implements Serializable {
@@ -15,13 +15,13 @@ public class Snapshot implements Serializable {
private Project project;
private Set<IDIYComponent<?>> selection;
private Map<IDIYComponent<?>, ComponentArea> areas;
private Set<Area> continuityAreas;
private Set<ContinuityArea> continuityAreas;
public Snapshot() {
}
public Snapshot(Project project, Set<IDIYComponent<?>> selection,
Map<IDIYComponent<?>, ComponentArea> areas, Set<Area> continuityAreas) {
Map<IDIYComponent<?>, ComponentArea> areas, Set<ContinuityArea> continuityAreas) {
super();
this.project = project;
this.selection = selection;
@@ -41,7 +41,7 @@ public class Snapshot implements Serializable {
return areas;
}
public Set<Area> getContinuityAreas() {
public Set<ContinuityArea> getContinuityAreas() {
return continuityAreas;
}
Binary file not shown.
@@ -30,6 +30,7 @@ import org.diylc.components.transform.AbstractBoardTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.ILayer;
import org.diylc.core.Project;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
@@ -44,7 +45,7 @@ import org.diylc.utils.Constants;
zOrder = IDIYComponent.BOARD, instanceNamePrefix = "Board", description = "Perforated board with solder pads",
bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false, keywordPolicy = KeywordPolicy.SHOW_TAG,
keywordTag = "Perf Board", transformer = AbstractBoardTransformer.class, enableCache = true)
public class PerfBoard extends AbstractBoard {
public class PerfBoard extends AbstractBoard implements ILayer {
private static final long serialVersionUID = 1L;
@@ -119,6 +120,11 @@ public class PerfBoard extends AbstractBoard {
@Override
public String getControlPointNodeName(int index) {
return null;
}
@Override
public int getLayerId() {
return 1;
}
@Override
@@ -31,6 +31,7 @@ import org.diylc.components.transform.VeroBoardTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.ILayer;
import org.diylc.core.Project;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
@@ -41,7 +42,7 @@ import org.diylc.utils.Constants;
instanceNamePrefix = "Board",
description = "Perforated FR4 board with copper strips connecting 3 holes in a row (aka TriPad Board)",
keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, transformer = VeroBoardTransformer.class, enableCache = true)
public class TriPadBoard extends AbstractVeroBoard {
public class TriPadBoard extends AbstractVeroBoard implements ILayer {
private static final long serialVersionUID = 1L;
@@ -202,5 +203,10 @@ public class TriPadBoard extends AbstractVeroBoard {
@Override
public String getControlPointNodeName(int index) {
return null;
}
@Override
public int getLayerId() {
return 1;
}
}
@@ -31,6 +31,7 @@ import org.diylc.components.transform.VeroBoardTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
import org.diylc.core.ILayer;
import org.diylc.core.Project;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
@@ -42,7 +43,7 @@ import org.diylc.utils.Constants;
description = "Perforated FR4 board with copper strips connecting all holes in a row",
bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, autoEdit = false, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME,
transformer = VeroBoardTransformer.class, enableCache = true)
public class VeroBoard extends AbstractVeroBoard {
public class VeroBoard extends AbstractVeroBoard implements ILayer {
private static final long serialVersionUID = 1L;
@@ -110,7 +111,10 @@ public class VeroBoard extends AbstractVeroBoard {
}
}
@Override
public int getLayerId() {
return 1;
}
@Override
public String getControlPointNodeName(int index) {
@@ -27,6 +27,7 @@ import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.CreationMethod;
import org.diylc.core.IDIYComponent;
import org.diylc.core.ILayer;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
@@ -40,7 +41,7 @@ import org.diylc.core.measures.SizeUnit;
description = "Straight copper trace", zOrder = IDIYComponent.TRACE, bomPolicy = BomPolicy.NEVER_SHOW,
autoEdit = false, keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "PCB",
transformer = SimpleComponentTransformer.class)
public class CopperTrace extends AbstractLeadedComponent<Void> {
public class CopperTrace extends AbstractLeadedComponent<Void> implements ILayer {
private static final long serialVersionUID = 1L;
@@ -99,6 +100,11 @@ public class CopperTrace extends AbstractLeadedComponent<Void> {
public void setLayer(PCBLayer layer) {
this.layer = layer;
}
@Override
public int getLayerId() {
return getLayer().getId();
}
@Override
protected float getLeadThickness() {
@@ -28,6 +28,7 @@ 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.ILayer;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
@@ -40,7 +41,7 @@ import org.diylc.core.measures.SizeUnit;
zOrder = IDIYComponent.TRACE, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "PCB", transformer = SimpleComponentTransformer.class,
enableCache = true)
public class CurvedTrace extends AbstractCurvedComponent<Void> {
public class CurvedTrace extends AbstractCurvedComponent<Void> implements ILayer {
private static final long serialVersionUID = 1L;
@@ -88,6 +89,11 @@ public class CurvedTrace extends AbstractCurvedComponent<Void> {
public void setLayer(PCBLayer layer) {
this.layer = layer;
}
@Override
public int getLayerId() {
return getLayer().getId();
}
@Override
public Void getValue() {
@@ -32,6 +32,7 @@ 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.ILayer;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.BomPolicy;
@@ -43,7 +44,7 @@ import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Ground Fill", author = "Branislav Stojkovic", category = "Connectivity",
instanceNamePrefix = "GF", description = "Polygonal ground fill area", zOrder = IDIYComponent.TRACE,
bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
public class GroundFill extends AbstractComponent<Void> {
public class GroundFill extends AbstractComponent<Void> implements ILayer {
private static final long serialVersionUID = 1L;
@@ -148,7 +149,11 @@ public class GroundFill extends AbstractComponent<Void> {
public void setLayer(PCBLayer layer) {
this.layer = layer;
}
@Override
public int getLayerId() {
return getLayer().getId();
}
@Deprecated
@Override
@@ -28,6 +28,7 @@ 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.ILayer;
import org.diylc.core.Project;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.BomPolicy;
@@ -44,7 +45,7 @@ import org.diylc.utils.Constants;
description = "Copper solder pad, round or square", instanceNamePrefix = "Pad",
zOrder = IDIYComponent.TRACE + 0.1, bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false,
keywordPolicy = KeywordPolicy.SHOW_TAG, keywordTag = "PCB", transformer = SimpleComponentTransformer.class, enableCache = true)
public class SolderPad extends AbstractComponent<Void> {
public class SolderPad extends AbstractComponent<Void> implements ILayer {
private static final long serialVersionUID = 1L;
@@ -128,6 +129,11 @@ public class SolderPad extends AbstractComponent<Void> {
public void setLayer(PCBLayer layer) {
this.layer = layer;
}
@Override
public int getLayerId() {
return getLayer().getId();
}
@Override
public String getName() {
@@ -93,7 +93,7 @@ public class SpiceAnalyzer extends NetlistAnalyzer implements INetlistAnalyzer {
if (c instanceof ISpiceMapper)
pointIndex = ((ISpiceMapper)c).mapToSpiceNode(pointIndex);
int nodeIndex = find(new Node(c, pointIndex), groups);
int nodeIndex = find(new Node(c, pointIndex, 0), groups);
if (nodeIndex < 0)
nodeIndex = unconnectedIndex++;
Binary file not shown.
Binary file not shown.