mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-15 15:58:41 -04:00
added new matrix transforms and closes #146
This commit is contained in:
parent
9d7cc23c47
commit
939ee8732d
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 -->
|
||||||
|
@ -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 -->
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user