added new matrix transforms and closes #146

This commit is contained in:
hneemann 2018-11-02 11:17:13 +01:00
parent 9d7cc23c47
commit 939ee8732d
16 changed files with 450 additions and 128 deletions

View File

@ -159,6 +159,15 @@ public final class Keys {
.allowGroupEdit() .allowGroupEdit()
.setSecondary(); .setSecondary();
/**
* The size of a seven seg display
*/
public static final Key<Integer> SEVEN_SEG_SIZE
= new Key.KeyInteger("Size", 2)
.setComboBoxValues(0, 1, 2, 3, 4, 5)
.setMin(0)
.allowGroupEdit();
/** /**
* The value of constants * The value of constants
*/ */

View File

@ -68,7 +68,8 @@ public class Out implements Element {
public static final ElementTypeDescription SEVENHEXDESCRIPTION public static final ElementTypeDescription SEVENHEXDESCRIPTION
= new ElementTypeDescription("Seven-Seg-Hex", = new ElementTypeDescription("Seven-Seg-Hex",
attributes -> new Out(4, 1), input("d"), input("dp")) attributes -> new Out(4, 1), input("d"), input("dp"))
.addAttribute(Keys.COLOR); .addAttribute(Keys.COLOR)
.addAttribute(Keys.SEVEN_SEG_SIZE);
/** /**
* Sixteen Segment Display * Sixteen Segment Display
@ -76,7 +77,8 @@ public class Out implements Element {
public static final ElementTypeDescription SIXTEENDESCRIPTION public static final ElementTypeDescription SIXTEENDESCRIPTION
= new ElementTypeDescription("SixteenSeg", = new ElementTypeDescription("SixteenSeg",
attributes -> new Out(16, 1), input("led"), input("dp")) attributes -> new Out(16, 1), input("led"), input("dp"))
.addAttribute(Keys.COLOR); .addAttribute(Keys.COLOR)
.addAttribute(Keys.SEVEN_SEG_SIZE);
private final int[] bits; private final int[] bits;
private final String label; private final String label;

View File

@ -8,7 +8,6 @@ package de.neemann.digital.draw.graphics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.StringTokenizer;
/** /**
* A polygon representation used by the {@link Graphic} interface. * A polygon representation used by the {@link Graphic} interface.
@ -198,6 +197,9 @@ public class Polygon implements Iterable<VectorInterface> {
* @return the transformed polygon * @return the transformed polygon
*/ */
public Polygon transform(Transform transform) { public Polygon transform(Transform transform) {
if (transform == Transform.IDENTITY)
return this;
Polygon p = new Polygon(closed); Polygon p = new Polygon(closed);
for (VectorInterface v : points) for (VectorInterface v : points)
p.add(v.transform(transform)); p.add(v.transform(transform));
@ -237,115 +239,14 @@ public class Polygon implements Iterable<VectorInterface> {
* @return the polygon or null if there was an error * @return the polygon or null if there was an error
*/ */
public static Polygon createFromPath(String path) { public static Polygon createFromPath(String path) {
StringTokenizer tok = new StringTokenizer(path, " ,"); try {
float x = 0; return new PolygonParser(path).create();
float y = 0; } catch (PolygonParser.ParserException e) {
Polygon p = new Polygon();
String lastTok = "";
while (tok.hasMoreTokens()) {
final String t = tok.nextToken();
switch (t) {
case "M":
x = Float.parseFloat(tok.nextToken());
y = Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
lastTok = t;
break;
case "m":
x += Float.parseFloat(tok.nextToken());
y += Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
lastTok = t;
break;
case "V":
y = Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
lastTok = t;
break;
case "v":
y += Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
lastTok = t;
break;
case "H":
x = Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
lastTok = t;
break;
case "h":
x += Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
lastTok = t;
break;
case "l":
x += Float.parseFloat(tok.nextToken());
y += Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
lastTok = t;
break;
case "L":
x = Float.parseFloat(tok.nextToken());
y = Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
lastTok = t;
break;
case "c":
float x1 = x + Float.parseFloat(tok.nextToken());
float y1 = y + Float.parseFloat(tok.nextToken());
float x2 = x1 + Float.parseFloat(tok.nextToken());
float y2 = y1 + Float.parseFloat(tok.nextToken());
x = x2 + Float.parseFloat(tok.nextToken());
y = y2 + Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x1, y1), new VectorFloat(x2, y2), new VectorFloat(x, y));
break;
case "C":
x1 = Float.parseFloat(tok.nextToken());
y1 = Float.parseFloat(tok.nextToken());
x2 = Float.parseFloat(tok.nextToken());
y2 = Float.parseFloat(tok.nextToken());
x = Float.parseFloat(tok.nextToken());
y = Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x1, y1), new VectorFloat(x2, y2), new VectorFloat(x, y));
break;
case "Z":
case "z":
p.closed = true;
break;
default:
switch (lastTok) {
case "V":
y = Float.parseFloat(t);
p.add(new VectorFloat(x, y));
break;
case "v":
y += Float.parseFloat(t);
p.add(new VectorFloat(x, y));
break;
case "H":
x = Float.parseFloat(t);
p.add(new VectorFloat(x, y));
break;
case "h":
x += Float.parseFloat(t);
p.add(new VectorFloat(x, y));
break;
case "l":
x += Float.parseFloat(t);
y += Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
break;
case "L":
x = Float.parseFloat(t);
y = Float.parseFloat(tok.nextToken());
p.add(new VectorFloat(x, y));
break;
default:
return null; return null;
} }
break;
}
}
return p;
} }
void setClosed(boolean closed) {
this.closed = closed;
}
} }

View File

@ -0,0 +1,186 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.draw.graphics;
/**
* Creates a polygon from a path
*/
public class PolygonParser {
enum Token {EOF, COMMAND, NUMBER}
private final String path;
private int lastTokenPos;
private int pos;
private char command;
private float value;
private float x;
private float y;
/**
* Creates a new instance
*
* @param path the path to parse
*/
PolygonParser(String path) {
this.path = path;
pos = 0;
}
Token next() {
lastTokenPos = pos;
while (pos < path.length() && (path.charAt(pos) == ' ' || path.charAt(pos) == ','))
pos++;
if (pos == path.length())
return Token.EOF;
char c = path.charAt(pos);
if (Character.isAlphabetic(c)) {
pos++;
command = c;
return Token.COMMAND;
} else {
value = parseNumber();
return Token.NUMBER;
}
}
private char peekChar() {
return path.charAt(pos);
}
private float parseNumber() {
int p0 = pos;
if (peekChar() == '+' || peekChar() == '-')
pos++;
while (pos < path.length() && (Character.isDigit(peekChar()) || peekChar() == '.'))
pos++;
if (pos < path.length() && (peekChar() == 'e' || peekChar() == 'E')) {
pos++;
if (peekChar() == '+' || peekChar() == '-')
pos++;
while (pos < path.length() && (Character.isDigit(peekChar()) || peekChar() == '.'))
pos++;
}
return Float.parseFloat(path.substring(p0, pos));
}
private void unreadToken() {
pos = lastTokenPos;
}
char getCommand() {
return command;
}
double getValue() {
return value;
}
private float nextValue() throws ParserException {
if (next() != Token.NUMBER)
throw new ParserException("expected a number at pos " + pos + " in '" + path + "'");
return value;
}
private VectorFloat nextVector() throws ParserException {
x = nextValue();
y = nextValue();
return new VectorFloat(x, y);
}
private VectorFloat nextVectorInc() throws ParserException {
x += nextValue();
y += nextValue();
return new VectorFloat(x, y);
}
/**
* Creates a polygon from the given path.
*
* @return the polygon
* @throws ParserException ParserException
*/
public Polygon create() throws ParserException {
Polygon p = new Polygon(false);
Token tok;
while ((tok = next()) != Token.EOF) {
if (tok == Token.NUMBER) {
unreadToken();
if (command == 'm')
command = 'l';
else if (command == 'M')
command = 'L';
}
switch (command) {
case 'M':
p.add(nextVector());
break;
case 'm':
p.add(nextVectorInc());
break;
case 'V':
y = nextValue();
p.add(new VectorFloat(x, y));
break;
case 'v':
y += nextValue();
p.add(new VectorFloat(x, y));
break;
case 'H':
x = nextValue();
p.add(new VectorFloat(x, y));
break;
case 'h':
x += nextValue();
p.add(new VectorFloat(x, y));
break;
case 'l':
p.add(nextVectorInc());
break;
case 'L':
p.add(nextVector());
break;
case 'c':
p.add(nextVectorInc(), nextVectorInc(), nextVectorInc());
break;
case 'C':
p.add(nextVector(), nextVector(), nextVector());
break;
case 'a':
addArc(p, nextVectorInc(), nextValue(), nextValue() != 0, nextValue() != 0, nextVectorInc());
break;
case 'A':
addArc(p, nextVector(), nextValue(), nextValue() != 0, nextValue() != 0, nextVector());
break;
case 'Z':
case 'z':
p.setClosed(true);
break;
default:
throw new ParserException("unsupported path command " + command);
}
}
return p;
}
private void addArc(Polygon p, VectorFloat rad, float rot, boolean large, boolean sweep, VectorFloat pos) {
p.add(pos);
}
/**
* The parser exception
*/
public static final class ParserException extends Exception {
private ParserException(String message) {
super(message);
}
}
}

View File

@ -10,6 +10,46 @@ package de.neemann.digital.draw.graphics;
*/ */
public interface Transform { public interface Transform {
/**
* The identity transform
*/
Transform IDENTITY = new Transform() {
@Override
public Vector transform(Vector v) {
return v;
}
@Override
public VectorFloat transform(VectorFloat v) {
return v;
}
@Override
public TransformMatrix getMatrix() {
return new TransformMatrix(1, 0, 0, 1, 0, 0);
}
};
/**
* Combines the two given transformations to a common transformation
*
* @param t1 first transformation
* @param t2 second transformation
* @return the resulting transformation
*/
static Transform mul(Transform t1, Transform t2) {
TransformMatrix m1 = t1.getMatrix();
TransformMatrix m2 = t2.getMatrix();
return new TransformMatrix(
m1.a * m2.a + m1.b * m2.c,
m1.c * m2.a + m1.d * m2.c,
m1.a * m2.b + m1.b * m2.d,
m1.c * m2.b + m1.d * m2.d,
m1.a * m2.x + m1.b * m2.y + m1.x,
m1.c * m2.x + m1.d * m2.y + m1.y);
}
/** /**
* Transforms an integer vector * Transforms an integer vector
* *
@ -26,4 +66,10 @@ public interface Transform {
*/ */
VectorFloat transform(VectorFloat v); VectorFloat transform(VectorFloat v);
/**
* Returns a matrix representation of this transformation
*
* @return the transformed Transform
*/
TransformMatrix getMatrix();
} }

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2018 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.draw.graphics;
/**
* A Matrix transformation
*/
public class TransformMatrix implements Transform {
/**
* Creates a rotation.
*
* @param w the angle in 360 grad
* @return the transformation
*/
public static TransformMatrix rotate(float w) {
final double phi = w / 180 * Math.PI;
float cos = (float) Math.cos(phi);
float sin = (float) Math.sin(phi);
return new TransformMatrix(cos, sin, -sin, cos, 0, 0);
}
final float a;
final float b;
final float c;
final float d;
final float x;
final float y;
/**
* Creates a new instance
*
* @param a A_00
* @param b A_10
* @param c A_01
* @param d A_11
* @param x x offset
* @param y y offset
*/
public TransformMatrix(float a, float b, float c, float d, float x, float y) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.x = x;
this.y = y;
}
@Override
public Vector transform(Vector v) {
return new Vector(
(int) (v.getXFloat() * a + v.getYFloat() * b + x),
(int) (v.getXFloat() * c + v.getYFloat() * d + y));
}
@Override
public VectorFloat transform(VectorFloat v) {
return new VectorFloat(
v.getXFloat() * a + v.getYFloat() * b + x,
v.getXFloat() * c + v.getYFloat() * d + y);
}
/**
* Transforms a direction vector
*
* @param v the vector to transform
* @return the transformed vector
*/
public VectorFloat transformDirection(VectorInterface v) {
return new VectorFloat(
v.getXFloat() * a + v.getYFloat() * b,
v.getXFloat() * c + v.getYFloat() * d);
}
@Override
public TransformMatrix getMatrix() {
return this;
}
}

View File

@ -53,4 +53,9 @@ public class TransformRotate implements Transform {
return new VectorFloat(v.getXFloat() * cos + v.getYFloat() * sin + translation.getXFloat(), return new VectorFloat(v.getXFloat() * cos + v.getYFloat() * sin + translation.getXFloat(),
-v.getXFloat() * sin + v.getYFloat() * cos + translation.getYFloat()); -v.getXFloat() * sin + v.getYFloat() * cos + translation.getYFloat());
} }
@Override
public TransformMatrix getMatrix() {
return new TransformMatrix(cos, sin, -sin, cos, translation.getXFloat(), translation.getYFloat());
}
} }

View File

@ -20,6 +20,16 @@ public class TransformTranslate implements Transform {
this.trans = trans; this.trans = trans;
} }
/**
* Creates a new instance
*
* @param x the x translation
* @param y the y translation
*/
public TransformTranslate(float x, float y) {
this(new VectorFloat(x, y));
}
@Override @Override
public Vector transform(Vector v) { public Vector transform(Vector v) {
return v.add(trans.getX(), trans.getY()); return v.add(trans.getX(), trans.getY());
@ -29,4 +39,9 @@ public class TransformTranslate implements Transform {
public VectorFloat transform(VectorFloat v) { public VectorFloat transform(VectorFloat v) {
return new VectorFloat(v.getXFloat() + trans.getXFloat(), v.getYFloat() + trans.getYFloat()); return new VectorFloat(v.getXFloat() + trans.getXFloat(), v.getYFloat() + trans.getYFloat());
} }
@Override
public TransformMatrix getMatrix() {
return new TransformMatrix(1, 0, 0, 1, trans.getXFloat(), trans.getYFloat());
}
} }

View File

@ -231,4 +231,9 @@ public class Vector implements VectorInterface {
public VectorInterface transform(Transform tr) { public VectorInterface transform(Transform tr) {
return tr.transform(this); return tr.transform(this);
} }
@Override
public Vector round() {
return this;
}
} }

View File

@ -120,4 +120,10 @@ public class VectorFloat implements VectorInterface {
public int hashCode() { public int hashCode() {
return Objects.hash(x, y); return Objects.hash(x, y);
} }
@Override
public Vector round() {
return new Vector(getX(), getY());
}
} }

View File

@ -66,4 +66,11 @@ public interface VectorInterface {
* @return the norm of this vector * @return the norm of this vector
*/ */
VectorFloat norm(); VectorFloat norm();
/**
* Rounds the vector to an int vector
*
* @return a int vector
*/
Vector round();
} }

View File

@ -7,10 +7,8 @@ package de.neemann.digital.draw.shapes;
import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.element.Keys;
import de.neemann.digital.draw.graphics.Graphic; import de.neemann.digital.draw.graphics.*;
import de.neemann.digital.draw.graphics.Polygon; import de.neemann.digital.draw.graphics.Polygon;
import de.neemann.digital.draw.graphics.Style;
import de.neemann.digital.draw.graphics.Vector;
import java.awt.*; import java.awt.*;
@ -39,6 +37,7 @@ public abstract class SevenShape implements Shape {
private final Style onStyle; private final Style onStyle;
private final Style offStyle; private final Style offStyle;
private final int size;
/** /**
* Creates a new instance * Creates a new instance
@ -48,16 +47,29 @@ public abstract class SevenShape implements Shape {
public SevenShape(ElementAttributes attr) { public SevenShape(ElementAttributes attr) {
onStyle = Style.NORMAL.deriveFillStyle(attr.get(Keys.COLOR)); onStyle = Style.NORMAL.deriveFillStyle(attr.get(Keys.COLOR));
offStyle = Style.NORMAL.deriveFillStyle(new Color(230, 230, 230)); offStyle = Style.NORMAL.deriveFillStyle(new Color(230, 230, 230));
size = attr.get(Keys.SEVEN_SEG_SIZE);
} }
@Override @Override
public void drawTo(Graphic graphic, Style highLight) { public void drawTo(Graphic graphic, Style highLight) {
graphic.drawPolygon(FRAME, Style.NORMAL); Transform tr = createTransform(size);
graphic.drawPolygon(FRAME.transform(tr), Style.NORMAL);
for (int i = 0; i < 7; i++) for (int i = 0; i < 7; i++)
graphic.drawPolygon(POLYGONS[i], getStyleInt(i)); graphic.drawPolygon(POLYGONS[i].transform(tr), getStyleInt(i));
graphic.drawCircle(DOT, DOT.add(8, 8), getStyleInt(7)); graphic.drawCircle(DOT.transform(tr), DOT.add(8, 8).transform(tr), getStyleInt(7));
}
static Transform createTransform(int size) {
if (size == 2)
return Transform.IDENTITY;
else {
final TransformTranslate tr1 = new TransformTranslate(-70, -139);
final TransformTranslate tr2 = new TransformTranslate(70, 139);
float s = (2 + size) / 4f;
final TransformMatrix trm = new TransformMatrix(s, 0, 0, s, 0, 0);
return Transform.mul(Transform.mul(tr2, trm), tr1);
}
} }
private Style getStyleInt(int i) { private Style getStyleInt(int i) {

View File

@ -14,10 +14,8 @@ import de.neemann.digital.core.element.PinDescriptions;
import de.neemann.digital.draw.elements.IOState; import de.neemann.digital.draw.elements.IOState;
import de.neemann.digital.draw.elements.Pin; import de.neemann.digital.draw.elements.Pin;
import de.neemann.digital.draw.elements.Pins; import de.neemann.digital.draw.elements.Pins;
import de.neemann.digital.draw.graphics.Graphic; import de.neemann.digital.draw.graphics.*;
import de.neemann.digital.draw.graphics.Polygon; import de.neemann.digital.draw.graphics.Polygon;
import de.neemann.digital.draw.graphics.Style;
import de.neemann.digital.draw.graphics.Vector;
import java.awt.*; import java.awt.*;
@ -54,6 +52,7 @@ public class SixteenShape implements Shape {
private final Style onStyle; private final Style onStyle;
private final Style offStyle; private final Style offStyle;
private final PinDescriptions pins; private final PinDescriptions pins;
private final int size;
private ObservableValue input; private ObservableValue input;
private ObservableValue dp; private ObservableValue dp;
private Value inValue; private Value inValue;
@ -70,6 +69,7 @@ public class SixteenShape implements Shape {
pins = inputs; pins = inputs;
onStyle = Style.NORMAL.deriveFillStyle(attr.get(Keys.COLOR)); onStyle = Style.NORMAL.deriveFillStyle(attr.get(Keys.COLOR));
offStyle = Style.NORMAL.deriveFillStyle(new Color(230, 230, 230)); offStyle = Style.NORMAL.deriveFillStyle(new Color(230, 230, 230));
size = attr.get(Keys.SEVEN_SEG_SIZE);
} }
@Override @Override
@ -96,7 +96,8 @@ public class SixteenShape implements Shape {
@Override @Override
public void drawTo(Graphic graphic, Style highLight) { public void drawTo(Graphic graphic, Style highLight) {
graphic.drawPolygon(SevenShape.FRAME, Style.NORMAL); Transform tr = SevenShape.createTransform(size);
graphic.drawPolygon(SevenShape.FRAME.transform(tr), Style.NORMAL);
int bits = -1; int bits = -1;
if (inValue != null) if (inValue != null)
@ -106,13 +107,13 @@ public class SixteenShape implements Shape {
for (Polygon p : POLYGONS) { for (Polygon p : POLYGONS) {
Style s = onStyle; Style s = onStyle;
if ((bits & mask) == 0) s = offStyle; if ((bits & mask) == 0) s = offStyle;
graphic.drawPolygon(p, s); graphic.drawPolygon(p.transform(tr), s);
mask <<= 1; mask <<= 1;
} }
Style s = onStyle; Style s = onStyle;
if (dpValue != null && !dpValue.getBool()) s = offStyle; if (dpValue != null && !dpValue.getBool()) s = offStyle;
graphic.drawCircle(DOT, DOT.add(8, 8), s); graphic.drawCircle(DOT.transform(tr), DOT.add(8, 8).transform(tr), s);
} }
} }

View File

@ -986,8 +986,8 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="key_Inputs_tt">Legt die Anzahl der Eingänge fest. Alle Eingänge müssen beschaltet werden.</string> <string name="key_Inputs_tt">Legt die Anzahl der Eingänge fest. Alle Eingänge müssen beschaltet werden.</string>
<string name="key_Label">Bezeichnung</string><!-- Out, LED, In, Clock, Button, Probe, LightBulb, LedMatrix, RotEncoder, Keyboard, Terminal, RS_FF, JK_FF, D_FF, T_FF, JK_FF_AS, D_FF_AS, Register, ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM, GraphicCard, Counter, Add, Sub, Mul, BarrelShifter, Comparator, Switch, Relay, PFET, NFET, FGPFET, FGNFET, Testcase, PowerSupply, Reset, Break --> <string name="key_Label">Bezeichnung</string><!-- Out, LED, In, Clock, Button, Probe, LightBulb, LedMatrix, RotEncoder, Keyboard, Terminal, RS_FF, JK_FF, D_FF, T_FF, JK_FF_AS, D_FF_AS, Register, ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM, GraphicCard, Counter, Add, Sub, Mul, BarrelShifter, Comparator, Switch, Relay, PFET, NFET, FGPFET, FGNFET, Testcase, PowerSupply, Reset, Break -->
<string name="key_Label_tt">Die Bezeichnung dieses Elementes.</string> <string name="key_Label_tt">Die Bezeichnung dieses Elementes.</string>
<string name="key_Size">Größe</string><!-- LED --> <string name="key_Size">Größe</string><!-- LED, SevenSeg -->
<string name="key_Size_tt">Die Größe der LED in der Schaltung.</string> <string name="key_Size_tt">Die Größe der Darstellung in der Schaltung.</string>
<string name="key_Language">Sprache</string> <string name="key_Language">Sprache</string>
<string name="key_Language_tt">Sprache der Oberfläche. Wird erst nach einem Neustart wirksam.</string> <string name="key_Language_tt">Sprache der Oberfläche. Wird erst nach einem Neustart wirksam.</string>
<string name="key_NetName">Netzname</string><!-- Tunnel --> <string name="key_NetName">Netzname</string><!-- Tunnel -->

View File

@ -981,8 +981,8 @@
<string name="key_Inputs_tt">The Number of Inputs used. Every input needs to be connected.</string> <string name="key_Inputs_tt">The Number of Inputs used. Every input needs to be connected.</string>
<string name="key_Label">Label</string><!-- Out, LED, In, Clock, Button, Probe, LightBulb, LedMatrix, RotEncoder, Keyboard, Terminal, RS_FF, JK_FF, D_FF, T_FF, JK_FF_AS, D_FF_AS, Register, ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM, GraphicCard, Counter, Add, Sub, Mul, BarrelShifter, Comparator, Switch, Relay, PFET, NFET, FGPFET, FGNFET, Testcase, PowerSupply, Reset, Break --> <string name="key_Label">Label</string><!-- Out, LED, In, Clock, Button, Probe, LightBulb, LedMatrix, RotEncoder, Keyboard, Terminal, RS_FF, JK_FF, D_FF, T_FF, JK_FF_AS, D_FF_AS, Register, ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM, GraphicCard, Counter, Add, Sub, Mul, BarrelShifter, Comparator, Switch, Relay, PFET, NFET, FGPFET, FGNFET, Testcase, PowerSupply, Reset, Break -->
<string name="key_Label_tt">The name of this element.</string> <string name="key_Label_tt">The name of this element.</string>
<string name="key_Size">Size</string><!-- LED --> <string name="key_Size">Size</string><!-- LED, SevenSeg -->
<string name="key_Size_tt">The size of the LED in the circuit.</string> <string name="key_Size_tt">The size of the shape in the circuit.</string>
<string name="key_Language">Language</string> <string name="key_Language">Language</string>
<string name="key_Language_tt">Language of the GUI. Will only take effect after a restart.</string> <string name="key_Language_tt">Language of the GUI. Will only take effect after a restart.</string>
<string name="key_NetName">Net name</string><!-- Tunnel --> <string name="key_NetName">Net name</string><!-- Tunnel -->

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2016 Helmut Neemann
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.draw.graphics;
import junit.framework.TestCase;
public class PolygonParserTest extends TestCase {
public void testSimple() {
PolygonParser pp = new PolygonParser("m 1,2");
assertEquals(PolygonParser.Token.COMMAND, pp.next());
assertEquals('m', pp.getCommand());
assertEquals(PolygonParser.Token.NUMBER, pp.next());
assertEquals(1.0, pp.getValue(), 1e-6);
assertEquals(PolygonParser.Token.NUMBER, pp.next());
assertEquals(2.0, pp.getValue(), 1e-6);
assertEquals(PolygonParser.Token.EOF, pp.next());
assertEquals(PolygonParser.Token.EOF, pp.next());
}
public void testSimpleExp() {
PolygonParser pp = new PolygonParser("1e1");
assertEquals(PolygonParser.Token.NUMBER, pp.next());
assertEquals(10, pp.getValue(), 1e-6);
assertEquals(PolygonParser.Token.EOF, pp.next());
}
public void testSimpleExpSign() {
PolygonParser pp = new PolygonParser("1e-1");
assertEquals(PolygonParser.Token.NUMBER, pp.next());
assertEquals(0.1, pp.getValue(), 1e-6);
assertEquals(PolygonParser.Token.EOF, pp.next());
}
}