first simple circuit generator, inputs still missing

This commit is contained in:
hneemann 2016-05-09 18:35:32 +02:00
parent ce49502f22
commit 7a3b7c77db
7 changed files with 186 additions and 51 deletions

View File

@ -1,7 +1,7 @@
package de.neemann.digital.analyse.expression; package de.neemann.digital.analyse.expression;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.TreeSet;
/** /**
* Visitor to collect all used variables in an expression * Visitor to collect all used variables in an expression
@ -10,13 +10,13 @@ import java.util.HashSet;
*/ */
public class VariableVisitor implements ExpressionVisitor { public class VariableVisitor implements ExpressionVisitor {
private final HashSet<Variable> variables; private final TreeSet<Variable> variables;
/** /**
* Creates a new instance * Creates a new instance
*/ */
public VariableVisitor() { public VariableVisitor() {
variables = new HashSet<>(); variables = new TreeSet<>();
} }
@Override @Override

View File

@ -1,11 +1,10 @@
package de.neemann.digital.draw.builder; package de.neemann.digital.draw.builder;
import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.*;
import de.neemann.digital.analyse.expression.Not;
import de.neemann.digital.analyse.expression.Operation;
import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.core.basic.And; import de.neemann.digital.core.basic.And;
import de.neemann.digital.core.basic.Or; import de.neemann.digital.core.basic.Or;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.io.Out;
import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.graphics.Vector;
import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementLibrary;
@ -15,26 +14,38 @@ import de.neemann.digital.gui.Main;
import javax.swing.*; import javax.swing.*;
import java.util.ArrayList; import java.util.ArrayList;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
/** /**
* @author hneemann * @author hneemann
*/ */
public class Builder { public class Builder {
private final Expression expression; private final Circuit circuit;
private ShapeFactory shapeFactory; private final VariableVisitor variableVisitor;
private final ShapeFactory shapeFactory;
private int pos;
public Builder(Expression expression, ShapeFactory shapeFactory) { public Builder(ShapeFactory shapeFactory) {
this.expression = expression;
this.shapeFactory = shapeFactory; this.shapeFactory = shapeFactory;
circuit = new Circuit();
variableVisitor = new VariableVisitor();
} }
public Circuit createCircuit() { public Builder addCircuit(String name, Expression expression) {
Fragment fr = createFragment(expression); Fragment fr = createFragment(expression);
fr = new FragmentExpression(fr, new FragmentVisualElement(Out.DESCRIPTION, shapeFactory).setAttr(Keys.LABEL, name));
fr.setPos(new Vector(0, 0)); fr.setPos(new Vector(0, 0));
fr.doLayout(); Box b = fr.doLayout();
Circuit circuit = new Circuit();
fr.addToCircuit(new Vector(0, 0), circuit); fr.addToCircuit(new Vector(0, pos), circuit);
return circuit; pos += b.getHeight() + SIZE;
expression.traverse(variableVisitor);
return this;
} }
private Fragment createFragment(Expression expression) { private Fragment createFragment(Expression expression) {
@ -52,23 +63,33 @@ public class Builder {
throw new RuntimeException("nyi"); throw new RuntimeException("nyi");
} else if (expression instanceof Not) { } else if (expression instanceof Not) {
Not n = (Not) expression; Not n = (Not) expression;
ArrayList<Fragment> frags = new ArrayList<>(); return new FragmentExpression(createFragment(n.getExpression()), new FragmentVisualElement(de.neemann.digital.core.basic.Not.DESCRIPTION, shapeFactory));
frags.add(createFragment(n.getExpression()));
return new FragmentExpression(frags, new FragmentVisualElement(de.neemann.digital.core.basic.Not.DESCRIPTION, frags.size(), shapeFactory));
} else if (expression instanceof Variable) { } else if (expression instanceof Variable) {
return new FragmentVariable(((Variable) expression)); return new FragmentVariable(((Variable) expression));
} else } else
throw new RuntimeException("nyi"); throw new RuntimeException("nyi");
} }
public Circuit getCircuit() {
return circuit;
}
public static void main(String[] args) { public static void main(String[] args) {
Variable a = new Variable("A"); Variable a = new Variable("A");
Variable b = new Variable("B"); Variable b = new Variable("B");
Variable c = new Variable("C"); Variable c = new Variable("C");
Expression e = Operation.or(Not.not(Operation.and(a, Not.not(b), c)), Operation.and(a, Not.not(c)), Operation.and(b, Not.not(c))); Expression y = Operation.or(Not.not(Operation.and(a, Not.not(b), c)), Operation.and(Not.not(a), c), Operation.and(b, Not.not(c)));
Builder builder = new Builder(e, new ShapeFactory(new ElementLibrary())); Expression y1 = Operation.or(Not.not(Operation.and(a, Not.not(b), c)), Operation.and(Not.not(a), c), Operation.and(b, Not.not(c)), Operation.and(b, Not.not(c)));
Circuit circuit = builder.createCircuit(); Expression l = Operation.and(y, y1, a);
Builder builder = new Builder(new ShapeFactory(new ElementLibrary()));
Circuit circuit = builder
.addCircuit("L", l)
.addCircuit("Y", y)
.getCircuit();
SwingUtilities.invokeLater(() -> new Main(null, circuit).setVisible(true)); SwingUtilities.invokeLater(() -> new Main(null, circuit).setVisible(true));
} }
} }

View File

@ -3,16 +3,21 @@ package de.neemann.digital.draw.builder;
import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.graphics.Vector;
import java.util.List;
/** /**
* @author hneemann * @author hneemann
*/ */
public interface Fragment { public interface Fragment {
Vector output();
Box doLayout(); Box doLayout();
void setPos(Vector pos); void setPos(Vector pos);
void addToCircuit(Vector pos, Circuit circuit); void addToCircuit(Vector pos, Circuit circuit);
List<Vector> getInputs();
List<Vector> getOutputs();
} }

View File

@ -1,9 +1,12 @@
package de.neemann.digital.draw.builder; package de.neemann.digital.draw.builder;
import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.Wire;
import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.graphics.Vector;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE; import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
@ -16,6 +19,16 @@ public class FragmentExpression implements Fragment {
private final Fragment merger; private final Fragment merger;
private Vector pos; private Vector pos;
private static ArrayList<Fragment> createList(Fragment fragment) {
ArrayList<Fragment> f = new ArrayList<>();
f.add(fragment);
return f;
}
public FragmentExpression(Fragment fragment, Fragment merger) {
this(createList(fragment), merger);
}
public FragmentExpression(ArrayList<Fragment> frags, Fragment merger) { public FragmentExpression(ArrayList<Fragment> frags, Fragment merger) {
this.merger = merger; this.merger = merger;
fragments = new ArrayList<>(); fragments = new ArrayList<>();
@ -23,33 +36,47 @@ public class FragmentExpression implements Fragment {
fragments.add(new FragmentHolder(fr)); fragments.add(new FragmentHolder(fr));
} }
@Override
public Vector output() {
return new Vector(0, 0);
}
@Override @Override
public Box doLayout() { public Box doLayout() {
int centerHeight = 0;
int height = 0; int height = 0;
int width = 0; int width = 0;
for (FragmentHolder fr : fragments) { int centerIndex = fragments.size() / 2;
for (int i = 0; i < fragments.size(); i++) {
FragmentHolder fr = fragments.get(i);
fr.fragment.setPos(new Vector(0, height)); fr.fragment.setPos(new Vector(0, height));
fr.box = fr.fragment.doLayout(); fr.box = fr.fragment.doLayout();
if (i == centerIndex)
centerHeight = height;
height += fr.box.getHeight(); height += fr.box.getHeight();
int w = fr.box.getWidth(); int w = fr.box.getWidth();
if (w > width) if (w > width)
width = w; width = w;
height += SIZE*2; height += SIZE * 2;
} }
height -= SIZE*2; height -= SIZE * 2;
Box mergerBox = merger.doLayout(); Box mergerBox = merger.doLayout();
width += SIZE; if (isLong())
if (fragments.size() > 3)
width += SIZE * 3;
else
width += SIZE * 2;
else
width += SIZE;
merger.setPos(new Vector(width, raster((height - mergerBox.getHeight()) / 2))); if ((fragments.size() & 1) == 0) {
// even number of inputs
merger.setPos(new Vector(width, raster((height - mergerBox.getHeight()) / 2)));
} else {
// odd number of inputs
int y = fragments.get(centerIndex).fragment.getOutputs().get(0).y - centerIndex * SIZE;
merger.setPos(new Vector(width, y));
}
width += mergerBox.getWidth(); width += mergerBox.getWidth();
@ -69,12 +96,52 @@ public class FragmentExpression implements Fragment {
public void addToCircuit(Vector offset, Circuit circuit) { public void addToCircuit(Vector offset, Circuit circuit) {
Vector p = pos.add(offset); Vector p = pos.add(offset);
merger.addToCircuit(p, circuit); merger.addToCircuit(p, circuit);
Iterator<Vector> inputs = merger.getInputs().iterator();
for (FragmentHolder fr : fragments) { for (FragmentHolder fr : fragments) {
fr.fragment.addToCircuit(p, circuit); fr.fragment.addToCircuit(p, circuit);
Vector pin = fr.fragment.getOutputs().get(0);
Vector start = pin.add(p);
Vector end = inputs.next().add(p);
if (isLong()) {
int dx = end.x - start.x - SIZE;
if (fragments.size() > 3)
dx -= SIZE;
Vector inter1 = start.add(dx, 0);
Vector inter2 = end.add(-SIZE, 0);
circuit.add(new Wire(start, inter1));
circuit.add(new Wire(inter1, inter2));
circuit.add(new Wire(inter2, end));
} else {
circuit.add(new Wire(start, end));
}
p.add(0, fr.box.getHeight() + SIZE); p.add(0, fr.box.getHeight() + SIZE);
} }
} }
@Override
public List<Vector> getInputs() {
ArrayList<Vector> pins = new ArrayList<>();
Vector p = new Vector(pos);
for (FragmentHolder fr : fragments) {
pins.addAll(Vector.add(fr.fragment.getInputs(), p));
p.add(0, fr.box.getHeight() + SIZE);
}
return pins;
}
@Override
public List<Vector> getOutputs() {
return Vector.add(merger.getOutputs(), pos);
}
public boolean isLong() {
return fragments.size() > 1;
}
private class FragmentHolder { private class FragmentHolder {
private final Fragment fragment; private final Fragment fragment;
private Box box; private Box box;

View File

@ -4,6 +4,9 @@ import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.graphics.Vector;
import java.util.ArrayList;
import java.util.List;
/** /**
* @author hneemann * @author hneemann
*/ */
@ -15,11 +18,6 @@ public class FragmentVariable implements Fragment {
this.variable = variable; this.variable = variable;
} }
@Override
public Vector output() {
return new Vector(0, 0);
}
@Override @Override
public Box doLayout() { public Box doLayout() {
return new Box(0, 0); return new Box(0, 0);
@ -33,4 +31,16 @@ public class FragmentVariable implements Fragment {
@Override @Override
public void addToCircuit(Vector pos, Circuit circuit) { public void addToCircuit(Vector pos, Circuit circuit) {
} }
@Override
public List<Vector> getInputs() {
return new ArrayList<>();
}
@Override
public List<Vector> getOutputs() {
ArrayList<Vector> o = new ArrayList<>();
o.add(pos);
return o;
}
} }

View File

@ -1,6 +1,7 @@
package de.neemann.digital.draw.builder; package de.neemann.digital.draw.builder;
import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.Key;
import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.PinDescription; import de.neemann.digital.core.element.PinDescription;
import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
@ -12,17 +13,22 @@ import de.neemann.digital.draw.graphics.Vector;
import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.draw.shapes.ShapeFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
* @author hneemann * @author hneemann
*/ */
public class FragmentVisualElement implements Fragment { public class FragmentVisualElement implements Fragment {
private final ArrayList<Pin> inputs; private final ArrayList<Vector> inputs;
private final ArrayList<Pin> outputs; private final ArrayList<Vector> outputs;
private final VisualElement visualElement; private final VisualElement visualElement;
private Vector pos; private Vector pos;
public FragmentVisualElement(ElementTypeDescription description, ShapeFactory shapeFactory) {
this(description, 1, shapeFactory);
}
public FragmentVisualElement(ElementTypeDescription description, int inputCount, ShapeFactory shapeFactory) { public FragmentVisualElement(ElementTypeDescription description, int inputCount, ShapeFactory shapeFactory) {
visualElement = new VisualElement(description.getName()).setShapeFactory(shapeFactory); visualElement = new VisualElement(description.getName()).setShapeFactory(shapeFactory);
visualElement.getElementAttributes().set(Keys.INPUT_COUNT, inputCount); visualElement.getElementAttributes().set(Keys.INPUT_COUNT, inputCount);
@ -32,24 +38,24 @@ public class FragmentVisualElement implements Fragment {
outputs = new ArrayList<>(); outputs = new ArrayList<>();
for (Pin p : pins) { for (Pin p : pins) {
if (p.getDirection().equals(PinDescription.Direction.input)) if (p.getDirection().equals(PinDescription.Direction.input))
inputs.add(p); inputs.add(p.getPos());
else else
outputs.add(p); outputs.add(p.getPos());
} }
} }
@Override public <VALUE> FragmentVisualElement setAttr(Key<VALUE> key, VALUE value) {
public Vector output() { visualElement.getElementAttributes().set(key, value);
return outputs.get(0).getPos(); return this;
} }
@Override @Override
public Box doLayout() { public Box doLayout() {
GraphicMinMax mm = new GraphicMinMax(); GraphicMinMax mm = new GraphicMinMax();
for (Pin p : inputs) for (Vector p : inputs)
mm.check(p.getPos()); mm.check(p);
for (Pin p : outputs) for (Vector p : outputs)
mm.check(p.getPos()); mm.check(p);
Vector delta = mm.getMax().sub(mm.getMin()); Vector delta = mm.getMax().sub(mm.getMin());
return new Box(delta.x, delta.y); return new Box(delta.x, delta.y);
} }
@ -61,8 +67,17 @@ public class FragmentVisualElement implements Fragment {
@Override @Override
public void addToCircuit(Vector offset, Circuit circuit) { public void addToCircuit(Vector offset, Circuit circuit) {
System.out.println(visualElement.getElementName() + ", " + pos + ", " + offset);
visualElement.setPos(pos.add(offset)); visualElement.setPos(pos.add(offset));
circuit.add(visualElement); circuit.add(visualElement);
} }
@Override
public List<Vector> getInputs() {
return Vector.add(inputs, pos);
}
@Override
public List<Vector> getOutputs() {
return Vector.add(outputs, pos);
}
} }

View File

@ -1,5 +1,8 @@
package de.neemann.digital.draw.graphics; package de.neemann.digital.draw.graphics;
import java.util.ArrayList;
import java.util.List;
/** /**
* Represents a 2D Vector * Represents a 2D Vector
* *
@ -191,4 +194,18 @@ public class Vector {
float l = (float) Math.sqrt(x * x + y * y); float l = (float) Math.sqrt(x * x + y * y);
return new Vector(Math.round(x * 128 / l), Math.round(y * 128 / l)); return new Vector(Math.round(x * 128 / l), Math.round(y * 128 / l));
} }
/**
* Adds a offset to every vector in the given list
*
* @param vectors the original vectors
* @param offs the offset
* @return the new list
*/
public static List<Vector> add(List<Vector> vectors, Vector offs) {
ArrayList<Vector> newVec = new ArrayList<>();
for (Vector v : vectors)
newVec.add(v.add(offs));
return newVec;
}
} }