lines consistency checker is running

This commit is contained in:
hneemann 2016-03-17 11:54:44 +01:00
parent 3b1e410d9a
commit e66a4e0369
7 changed files with 426 additions and 5 deletions

View File

@ -23,7 +23,6 @@ public class CircuitComponent extends JComponent {
private static final String delAction = "myDelAction";
private final Circuit circuit;
;
private Mouse listener;
public CircuitComponent(Circuit circuit) {

View File

@ -78,4 +78,23 @@ public class Vector implements Moveable {
public boolean inside(Vector min, Vector max) {
return min.x <= x && x <= max.x && min.y <= y && y <= max.y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Vector vector = (Vector) o;
if (x != vector.x) return false;
return y == vector.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}

View File

@ -1,6 +1,7 @@
package de.neemann.digital.gui.draw.parts;
import de.neemann.digital.gui.draw.graphics.Graphic;
import de.neemann.digital.gui.draw.graphics.Style;
import de.neemann.digital.gui.draw.graphics.Vector;
import de.neemann.digital.gui.draw.shapes.Drawable;
@ -11,19 +12,23 @@ import java.util.Iterator;
* @author hneemann
*/
public class Circuit implements Drawable {
private static final Vector RAD = new Vector(2, 2);
private final ArrayList<VisualPart> visualParts;
private final ArrayList<Wire> wires;
private transient ArrayList<Vector> dots;
private ArrayList<Wire> wires;
public Circuit() {
visualParts = new ArrayList<>();
wires = new ArrayList<>();
dots = new ArrayList<>();
}
@Override
public void drawTo(Graphic graphic) {
for (Wire w : wires)
w.drawTo(graphic);
for (Vector d : dots)
graphic.drawCircle(d.sub(RAD), d.add(RAD), Style.WIRE);
for (VisualPart p : visualParts)
p.drawTo(graphic);
}
@ -32,8 +37,27 @@ public class Circuit implements Drawable {
visualParts.add(visualPart);
}
public void add(Wire wire) {
wires.add(wire);
public void add(Wire newWire) {
if (newWire.p1.equals(newWire.p2))
return;
int len = wires.size();
for (int i = 0; i < len; i++) {
Wire present = wires.get(i);
if (present.contains(newWire.p1)) {
wires.set(i, new Wire(present.p1, newWire.p1));
wires.add(new Wire(present.p2, newWire.p1));
} else if (present.contains(newWire.p2)) {
wires.set(i, new Wire(present.p1, newWire.p2));
wires.add(new Wire(present.p2, newWire.p2));
}
;
}
wires.add(newWire);
WireConsistencyChecker checker = new WireConsistencyChecker(wires);
wires = checker.check();
dots = WireConsistencyChecker.createDots(wires);
}
public ArrayList<VisualPart> getParts() {

View File

@ -32,4 +32,50 @@ public class Wire implements Drawable, Moveable {
public void setP2(Vector p2) {
this.p2 = p2;
}
public boolean contains(Vector v) {
if (p1.x == p2.x && p1.x == v.x)
return (p1.y < v.y && v.y < p2.y) || (p2.y < v.y && v.y < p1.y);
else if (p1.y == p2.y && p1.y == v.y)
return (p1.x < v.x && v.x < p2.x) || (p2.x < v.x && v.x < p1.x);
else
return false;
}
public Orientation getOrientation() {
if (p1.x == p2.x)
return Orientation.vertical;
if (p1.y == p2.y)
return Orientation.horzontal;
return Orientation.diagonal;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Wire wire = (Wire) o;
if (!p1.equals(wire.p1)) return false;
return p2.equals(wire.p2);
}
@Override
public int hashCode() {
int result = p1.hashCode();
result = 31 * result + p2.hashCode();
return result;
}
@Override
public String toString() {
return "Wire{" +
"p1=" + p1 +
", p2=" + p2 +
'}';
}
enum Orientation {horzontal, vertical, diagonal}
}

View File

@ -0,0 +1,85 @@
package de.neemann.digital.gui.draw.parts;
import de.neemann.digital.gui.draw.graphics.Vector;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* @author hneemann
*/
public class WireConsistencyChecker {
private ArrayList<Wire> wires;
public WireConsistencyChecker(ArrayList<Wire> wires) {
this.wires = wires;
}
public static ArrayList<Vector> createDots(ArrayList<Wire> wires) {
HashMap<Vector, Counter> map = new HashMap<>();
for (Wire w : wires) {
inc(map, w.p1);
inc(map, w.p2);
}
ArrayList<Vector> dots = new ArrayList<>();
for (Map.Entry<Vector, Counter> e : map.entrySet())
if (e.getValue().counter > 2)
dots.add(e.getKey());
return dots;
}
private static void inc(HashMap<Vector, Counter> map, Vector vector) {
Counter c = map.get(vector);
if (c == null) {
c = new Counter();
map.put(vector, c);
}
c.inc();
}
public ArrayList<Wire> check() {
wires = merge(wires);
return wires;
}
private ArrayList<Wire> merge(ArrayList<Wire> wires) {
ArrayList<Vector> dots = createDots(wires);
ArrayList<Wire> newWires = new ArrayList<>();
WireMerger hori = new WireMerger(Wire.Orientation.horzontal);
WireMerger vert = new WireMerger(Wire.Orientation.vertical);
for (Wire w : wires) {
if (!w.p1.equals(w.p2))
switch (w.getOrientation()) {
case horzontal:
hori.add(w);
break;
case vertical:
vert.add(w);
break;
default:
newWires.add(w);
}
}
hori.protectDots(dots);
vert.protectDots(dots);
hori.addTo(newWires);
vert.addTo(newWires);
return newWires;
}
private static class Counter {
private int counter;
public void inc() {
counter++;
}
}
}

View File

@ -0,0 +1,173 @@
package de.neemann.digital.gui.draw.parts;
import de.neemann.digital.gui.draw.graphics.Vector;
import java.util.ArrayList;
import java.util.HashMap;
/**
* @author hneemann
*/
public class WireMerger {
private HashMap<Integer, WireContainer> wireContainers;
private OrientationHandler handler;
public WireMerger(Wire.Orientation orientation) {
wireContainers = new HashMap<>();
switch (orientation) {
case horzontal:
handler = new OrientationHandlerHorizontal();
break;
case vertical:
handler = new OrientationHandlerVertical();
break;
default:
throw new RuntimeException("wrong line orientation");
}
}
public void add(Wire w) {
SimpleWire sw = new SimpleWire(handler.getWireClass(w.p1), handler.getS(w.p1), handler.getS(w.p2));
WireContainer wc = wireContainers.get(sw.wireClass);
if (wc == null) {
wc = new WireContainer(sw.wireClass);
wireContainers.put(sw.wireClass, wc);
}
wc.add(sw);
}
public void addTo(ArrayList<Wire> wires) {
for (WireContainer wc : wireContainers.values()) {
wc.addTo(wires);
}
}
public void protectDots(ArrayList<Vector> dots) {
for (Vector v : dots) {
WireContainer wc = wireContainers.get(handler.getWireClass(v));
if (wc != null) // is possible because diagonals are not included
wc.protect(handler.getS(v));
}
}
interface OrientationHandler {
Wire toWire(SimpleWire wire);
int getS(Vector v);
int getWireClass(Vector v);
}
public static class SimpleWire {
protected int wireClass;
protected int s1;
protected int s2;
public SimpleWire(int wireClass, int s1, int s2) {
this.wireClass = wireClass;
if (s2 < s1) {
this.s1 = s2;
this.s2 = s1;
} else {
this.s1 = s1;
this.s2 = s2;
}
}
public boolean tryMerge(SimpleWire other) {
if (s2 < other.s1 || other.s2 < s1)
return false;
else {
s1 = Math.min(s1, other.s1);
s2 = Math.max(s2, other.s2);
return true;
}
}
public boolean containsAsInner(int s) {
return s1 < s && s2 > s;
}
}
public static class OrientationHandlerHorizontal implements OrientationHandler {
@Override
public Wire toWire(SimpleWire wire) {
return new Wire(new Vector(wire.s1, wire.wireClass), new Vector(wire.s2, wire.wireClass));
}
@Override
public int getWireClass(Vector v) {
return v.y;
}
@Override
public int getS(Vector v) {
return v.x;
}
}
public static class OrientationHandlerVertical implements OrientationHandler {
@Override
public Wire toWire(SimpleWire wire) {
return new Wire(new Vector(wire.wireClass, wire.s1), new Vector(wire.wireClass, wire.s2));
}
@Override
public int getS(Vector v) {
return v.y;
}
@Override
public int getWireClass(Vector v) {
return v.x;
}
}
private class WireContainer {
public int wireClass;
public ArrayList<SimpleWire> wires;
public WireContainer(int wireClass) {
this.wireClass = wireClass;
wires = new ArrayList<>();
}
public void add(SimpleWire newSimpleWire) {
wires.add(newSimpleWire);
simplify(newSimpleWire);
}
private void simplify(SimpleWire changedWire) {
for (SimpleWire wire : wires) {
if (!wire.equals(changedWire)) {
if (wire.tryMerge(changedWire)) {
wires.remove(changedWire);
simplify(wire);
return;
}
}
}
}
public void addTo(ArrayList<Wire> list) {
for (SimpleWire sw : wires)
list.add(handler.toWire(sw));
}
public void protect(int s) {
int len = wires.size();
for (int i = 0; i < len; i++) {
SimpleWire sw = wires.get(i);
if (sw.containsAsInner(s)) {
int s2 = sw.s2;
sw.s2 = s;
wires.add(new SimpleWire(wireClass, s, s2));
}
}
}
}
}

View File

@ -0,0 +1,75 @@
package de.neemann.digital.gui.draw.parts;
import de.neemann.digital.gui.draw.graphics.Vector;
import junit.framework.TestCase;
import java.util.ArrayList;
/**
* @author hneemann
*/
public class WireMergerTest extends TestCase {
public void testHorizontal() {
WireMerger.OrientationHandler handler = new WireMerger.OrientationHandlerHorizontal();
assertEquals(1, handler.getS(new Vector(1, 3)));
assertEquals(3, handler.getWireClass(new Vector(1, 3)));
Wire wire = handler.toWire(new WireMerger.SimpleWire(1, 3, 7));
assertEquals(new Vector(3, 1), wire.p1);
assertEquals(new Vector(7, 1), wire.p2);
}
public void testVertical() {
WireMerger.OrientationHandler handler = new WireMerger.OrientationHandlerVertical();
assertEquals(1, handler.getS(new Vector(3, 1)));
assertEquals(3, handler.getWireClass(new Vector(3, 1)));
Wire wire = handler.toWire(new WireMerger.SimpleWire(1, 3, 7));
assertEquals(new Vector(1, 3), wire.p1);
assertEquals(new Vector(1, 7), wire.p2);
}
public void testMerge1() {
WireMerger wm = new WireMerger(Wire.Orientation.horzontal);
wm.add(new Wire(new Vector(1, 3), new Vector(5, 3)));
wm.add(new Wire(new Vector(5, 3), new Vector(8, 3)));
wm.add(new Wire(new Vector(1, 4), new Vector(5, 4)));
wm.add(new Wire(new Vector(5, 5), new Vector(8, 5)));
wm.add(new Wire(new Vector(1, 6), new Vector(6, 6)));
wm.add(new Wire(new Vector(4, 6), new Vector(8, 6)));
wm.add(new Wire(new Vector(1, 7), new Vector(4, 7)));
wm.add(new Wire(new Vector(5, 7), new Vector(8, 7)));
ArrayList<Wire> newWires = new ArrayList<>();
wm.addTo(newWires);
assertEquals(6, newWires.size());
assertTrue(newWires.contains(new Wire(new Vector(1, 3), new Vector(8, 3))));
assertTrue(newWires.contains(new Wire(new Vector(1, 4), new Vector(5, 4))));
assertTrue(newWires.contains(new Wire(new Vector(5, 5), new Vector(8, 5))));
assertTrue(newWires.contains(new Wire(new Vector(1, 6), new Vector(8, 6))));
assertTrue(newWires.contains(new Wire(new Vector(1, 7), new Vector(4, 7))));
assertTrue(newWires.contains(new Wire(new Vector(5, 7), new Vector(8, 7))));
}
public void testMerge2() {
WireMerger wm = new WireMerger(Wire.Orientation.horzontal);
wm.add(new Wire(new Vector(1, 3), new Vector(3, 3)));
wm.add(new Wire(new Vector(6, 3), new Vector(8, 3)));
wm.add(new Wire(new Vector(2, 3), new Vector(7, 3)));
ArrayList<Wire> newWires = new ArrayList<>();
wm.addTo(newWires);
assertEquals(1, newWires.size());
assertEquals(new Wire(new Vector(1, 3), new Vector(8, 3)), newWires.get(0));
}
}