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

View File

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

View File

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

View File

@ -1,9 +1,12 @@
package de.neemann.digital.draw.builder;
import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.Wire;
import de.neemann.digital.draw.graphics.Vector;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
@ -16,6 +19,16 @@ public class FragmentExpression implements Fragment {
private final Fragment merger;
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) {
this.merger = merger;
fragments = new ArrayList<>();
@ -23,33 +36,47 @@ public class FragmentExpression implements Fragment {
fragments.add(new FragmentHolder(fr));
}
@Override
public Vector output() {
return new Vector(0, 0);
}
@Override
public Box doLayout() {
int centerHeight = 0;
int height = 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.box = fr.fragment.doLayout();
if (i == centerIndex)
centerHeight = height;
height += fr.box.getHeight();
int w = fr.box.getWidth();
if (w > width)
width = w;
height += SIZE*2;
height += SIZE * 2;
}
height -= SIZE*2;
height -= SIZE * 2;
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();
@ -69,12 +96,52 @@ public class FragmentExpression implements Fragment {
public void addToCircuit(Vector offset, Circuit circuit) {
Vector p = pos.add(offset);
merger.addToCircuit(p, circuit);
Iterator<Vector> inputs = merger.getInputs().iterator();
for (FragmentHolder fr : fragments) {
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);
}
}
@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 final Fragment fragment;
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.graphics.Vector;
import java.util.ArrayList;
import java.util.List;
/**
* @author hneemann
*/
@ -15,11 +18,6 @@ public class FragmentVariable implements Fragment {
this.variable = variable;
}
@Override
public Vector output() {
return new Vector(0, 0);
}
@Override
public Box doLayout() {
return new Box(0, 0);
@ -33,4 +31,16 @@ public class FragmentVariable implements Fragment {
@Override
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;
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.PinDescription;
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 java.util.ArrayList;
import java.util.List;
/**
* @author hneemann
*/
public class FragmentVisualElement implements Fragment {
private final ArrayList<Pin> inputs;
private final ArrayList<Pin> outputs;
private final ArrayList<Vector> inputs;
private final ArrayList<Vector> outputs;
private final VisualElement visualElement;
private Vector pos;
public FragmentVisualElement(ElementTypeDescription description, ShapeFactory shapeFactory) {
this(description, 1, shapeFactory);
}
public FragmentVisualElement(ElementTypeDescription description, int inputCount, ShapeFactory shapeFactory) {
visualElement = new VisualElement(description.getName()).setShapeFactory(shapeFactory);
visualElement.getElementAttributes().set(Keys.INPUT_COUNT, inputCount);
@ -32,24 +38,24 @@ public class FragmentVisualElement implements Fragment {
outputs = new ArrayList<>();
for (Pin p : pins) {
if (p.getDirection().equals(PinDescription.Direction.input))
inputs.add(p);
inputs.add(p.getPos());
else
outputs.add(p);
outputs.add(p.getPos());
}
}
@Override
public Vector output() {
return outputs.get(0).getPos();
public <VALUE> FragmentVisualElement setAttr(Key<VALUE> key, VALUE value) {
visualElement.getElementAttributes().set(key, value);
return this;
}
@Override
public Box doLayout() {
GraphicMinMax mm = new GraphicMinMax();
for (Pin p : inputs)
mm.check(p.getPos());
for (Pin p : outputs)
mm.check(p.getPos());
for (Vector p : inputs)
mm.check(p);
for (Vector p : outputs)
mm.check(p);
Vector delta = mm.getMax().sub(mm.getMin());
return new Box(delta.x, delta.y);
}
@ -61,8 +67,17 @@ public class FragmentVisualElement implements Fragment {
@Override
public void addToCircuit(Vector offset, Circuit circuit) {
System.out.println(visualElement.getElementName() + ", " + pos + ", " + offset);
visualElement.setPos(pos.add(offset));
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;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a 2D Vector
*
@ -191,4 +194,18 @@ public class Vector {
float l = (float) Math.sqrt(x * x + y * y);
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;
}
}