mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-13 06:49:36 -04:00
lines consistency checker is running
This commit is contained in:
parent
3b1e410d9a
commit
e66a4e0369
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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}
|
||||
}
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
173
src/main/java/de/neemann/digital/gui/draw/parts/WireMerger.java
Normal file
173
src/main/java/de/neemann/digital/gui/draw/parts/WireMerger.java
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user