mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-16 08:25:09 -04:00
first simple circuit generator, inputs still missing
This commit is contained in:
parent
ce49502f22
commit
7a3b7c77db
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user