kopia lustrzana https://github.com/jameshball/osci-render
Complete initial working implementation of SvgParser with argument passing
rodzic
ef63e47b94
commit
d80a7aadf8
Przed Szerokość: | Wysokość: | Rozmiar: 541 B Po Szerokość: | Wysokość: | Rozmiar: 541 B |
|
@ -1,11 +1,20 @@
|
||||||
package audio;
|
package audio;
|
||||||
|
|
||||||
import engine.Camera;
|
import engine.Camera;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import parser.FileParser;
|
||||||
|
import parser.ObjParser;
|
||||||
|
import parser.SvgParser;
|
||||||
|
import shapes.Shape;
|
||||||
|
import shapes.Shapes;
|
||||||
|
|
||||||
// Helper class for AudioClient that deals with optional program arguments.
|
// Helper class for AudioClient that deals with optional program arguments.
|
||||||
final class AudioArgs {
|
final class AudioArgs {
|
||||||
|
|
||||||
final String objFilePath;
|
final String filePath;
|
||||||
final float[] optionalArgs;
|
final float[] optionalArgs;
|
||||||
|
|
||||||
AudioArgs(String[] args) throws IllegalAudioArgumentException {
|
AudioArgs(String[] args) throws IllegalAudioArgumentException {
|
||||||
|
@ -13,7 +22,7 @@ final class AudioArgs {
|
||||||
throw new IllegalAudioArgumentException();
|
throw new IllegalAudioArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
objFilePath = args[0];
|
filePath = args[0];
|
||||||
optionalArgs = new float[args.length - 1];
|
optionalArgs = new float[args.length - 1];
|
||||||
|
|
||||||
for (int i = 0; i < optionalArgs.length; i++) {
|
for (int i = 0; i < optionalArgs.length; i++) {
|
||||||
|
@ -21,8 +30,16 @@ final class AudioArgs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String objFilePath() {
|
List<List<Shape>> getFramesFromFile() throws IOException, ParserConfigurationException, SAXException {
|
||||||
return objFilePath;
|
if (filePath.matches(".*\\.obj")) {
|
||||||
|
return new ObjParser(filePath, rotateSpeed(), cameraX(), cameraY(), cameraZ(), focalLength(),
|
||||||
|
isDefaultPosition()).getShapes();
|
||||||
|
} else if (filePath.matches(".*\\.svg")) {
|
||||||
|
return Shapes.normalize(new SvgParser(filePath).getShapes());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Provided file extension in file " + filePath + " not supported.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float rotateSpeed() {
|
float rotateSpeed() {
|
||||||
|
|
|
@ -1,24 +1,15 @@
|
||||||
package audio;
|
package audio;
|
||||||
|
|
||||||
import engine.Camera;
|
|
||||||
import engine.Vector3;
|
|
||||||
import engine.WorldObject;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import parser.SvgParser;
|
|
||||||
import shapes.Shape;
|
import shapes.Shape;
|
||||||
import shapes.Shapes;
|
|
||||||
import shapes.Vector2;
|
import shapes.Vector2;
|
||||||
|
|
||||||
public class AudioClient {
|
public class AudioClient {
|
||||||
|
|
||||||
private static final int SAMPLE_RATE = 192000;
|
private static final int SAMPLE_RATE = 192000;
|
||||||
private static double OBJ_ROTATE_SPEED = Math.PI / 1000;
|
|
||||||
private static final float ROTATE_SPEED = 0;
|
private static final float ROTATE_SPEED = 0;
|
||||||
private static final float TRANSLATION_SPEED = 0;
|
private static final float TRANSLATION_SPEED = 0;
|
||||||
private static final Vector2 TRANSLATION = new Vector2(0.3, 0.3);
|
private static final Vector2 TRANSLATION = new Vector2(0.3, 0.3);
|
||||||
|
@ -26,7 +17,7 @@ public class AudioClient {
|
||||||
private static final float WEIGHT = Shape.DEFAULT_WEIGHT;
|
private static final float WEIGHT = Shape.DEFAULT_WEIGHT;
|
||||||
|
|
||||||
// args:
|
// args:
|
||||||
// args[0] - path of .obj file
|
// args[0] - path of .obj or .svg file
|
||||||
// args[1] - rotation speed of object
|
// args[1] - rotation speed of object
|
||||||
// args[2] - focal length of camera
|
// args[2] - focal length of camera
|
||||||
// args[3] - x position of camera
|
// args[3] - x position of camera
|
||||||
|
@ -44,23 +35,8 @@ public class AudioClient {
|
||||||
|
|
||||||
AudioArgs args = new AudioArgs(programArgs);
|
AudioArgs args = new AudioArgs(programArgs);
|
||||||
|
|
||||||
OBJ_ROTATE_SPEED *= args.rotateSpeed();
|
|
||||||
|
|
||||||
Vector3 cameraPos = new Vector3(args.cameraX(), args.cameraY(), args.cameraZ());
|
|
||||||
WorldObject object = new WorldObject(args.objFilePath());
|
|
||||||
|
|
||||||
// If camera position arguments haven't been specified, automatically work out the position of
|
|
||||||
// the camera based on the size of the object in the camera's view.
|
|
||||||
Camera camera = args.isDefaultPosition() ? new Camera(args.focalLength(), object)
|
|
||||||
: new Camera(args.focalLength(), cameraPos);
|
|
||||||
|
|
||||||
Vector3 rotation = new Vector3(0, OBJ_ROTATE_SPEED, OBJ_ROTATE_SPEED);
|
|
||||||
|
|
||||||
System.out.println("Begin pre-render...");
|
System.out.println("Begin pre-render...");
|
||||||
//List<List<? extends Shape>> frames = preRender(object, rotation, camera);
|
List<List<Shape>> frames = args.getFramesFromFile();
|
||||||
List<List<? extends Shape>> frames = new ArrayList<>();
|
|
||||||
List<Shape> frame = Shapes.normalizeShapes(new SvgParser("test/images/sine-wave.svg").getShapes());
|
|
||||||
frames.add(frame);
|
|
||||||
System.out.println("Finish pre-render");
|
System.out.println("Finish pre-render");
|
||||||
System.out.println("Connecting to audio player");
|
System.out.println("Connecting to audio player");
|
||||||
AudioPlayer player = new AudioPlayer(SAMPLE_RATE, frames, ROTATE_SPEED, TRANSLATION_SPEED,
|
AudioPlayer player = new AudioPlayer(SAMPLE_RATE, frames, ROTATE_SPEED, TRANSLATION_SPEED,
|
||||||
|
@ -68,33 +44,4 @@ public class AudioClient {
|
||||||
System.out.println("Starting audio stream");
|
System.out.println("Starting audio stream");
|
||||||
player.play();
|
player.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<List<? extends Shape>> preRender(WorldObject object, Vector3 rotation,
|
|
||||||
Camera camera) {
|
|
||||||
List<List<? extends Shape>> preRenderedFrames = new ArrayList<>();
|
|
||||||
// Number of frames it will take to render a full rotation of the object.
|
|
||||||
int numFrames = (int) (2 * Math.PI / OBJ_ROTATE_SPEED);
|
|
||||||
|
|
||||||
for (int i = 0; i < numFrames; i++) {
|
|
||||||
preRenderedFrames.add(new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
AtomicInteger renderedFrames = new AtomicInteger();
|
|
||||||
|
|
||||||
// pre-renders the WorldObject in parallel
|
|
||||||
IntStream.range(0, numFrames).parallel().forEach((frameNum) -> {
|
|
||||||
WorldObject clone = object.clone();
|
|
||||||
clone.rotate(rotation.scale(frameNum));
|
|
||||||
// Finds all lines to draw the object from the camera's view and then 'sorts' them by finding
|
|
||||||
// a hamiltonian path, which dramatically helps with rendering a clean image.
|
|
||||||
preRenderedFrames.set(frameNum, Shapes.sortLines(camera.draw(clone)));
|
|
||||||
int numRendered = renderedFrames.getAndIncrement();
|
|
||||||
|
|
||||||
if (numRendered % 50 == 0) {
|
|
||||||
System.out.println("Rendered " + numRendered + " frames of " + (numFrames + 1) + " total");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return preRenderedFrames;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -18,7 +18,7 @@ public class AudioPlayer {
|
||||||
|
|
||||||
private final XtFormat FORMAT;
|
private final XtFormat FORMAT;
|
||||||
|
|
||||||
private final List<List<? extends Shape>> frames;
|
private final List<List<Shape>> frames;
|
||||||
private int currentFrame = 0;
|
private int currentFrame = 0;
|
||||||
private int currentShape = 0;
|
private int currentShape = 0;
|
||||||
private int audioFramesDrawn = 0;
|
private int audioFramesDrawn = 0;
|
||||||
|
@ -33,12 +33,12 @@ public class AudioPlayer {
|
||||||
|
|
||||||
private volatile boolean stopped;
|
private volatile boolean stopped;
|
||||||
|
|
||||||
public AudioPlayer(int sampleRate, List<List<? extends Shape>> frames) {
|
public AudioPlayer(int sampleRate, List<List<Shape>> frames) {
|
||||||
this.FORMAT = new XtFormat(new XtMix(sampleRate, XtSample.FLOAT32), 0, 0, 2, 0);
|
this.FORMAT = new XtFormat(new XtMix(sampleRate, XtSample.FLOAT32), 0, 0, 2, 0);
|
||||||
this.frames = frames;
|
this.frames = frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AudioPlayer(int sampleRate, List<List<? extends Shape>> frames, float rotateSpeed,
|
public AudioPlayer(int sampleRate, List<List<Shape>> frames, float rotateSpeed,
|
||||||
float translateSpeed, Vector2 translateVector, float scale, float weight) {
|
float translateSpeed, Vector2 translateVector, float scale, float weight) {
|
||||||
this(sampleRate, frames);
|
this(sampleRate, frames);
|
||||||
setRotateSpeed(rotateSpeed);
|
setRotateSpeed(rotateSpeed);
|
||||||
|
|
|
@ -2,25 +2,27 @@ package parser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import shapes.Shape;
|
import shapes.Shape;
|
||||||
|
|
||||||
public abstract class FileParser {
|
public abstract class FileParser {
|
||||||
|
|
||||||
public abstract String getFileExtension();
|
protected abstract String getFileExtension();
|
||||||
|
|
||||||
protected void checkFileExtension(String path) throws IllegalArgumentException {
|
protected void checkFileExtension(String path) throws IllegalArgumentException {
|
||||||
Pattern pattern = Pattern.compile("\\." + getFileExtension() + "$");
|
if (!hasCorrectFileExtension(path)) {
|
||||||
if (!pattern.matcher(path).find()) {
|
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"File to parse is not a ." + getFileExtension() + " file.");
|
"File to parse is not a ." + getFileExtension() + " file.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasCorrectFileExtension(String path) {
|
||||||
|
return path.matches(".*\\." + getFileExtension());
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void parseFile(String path)
|
protected abstract void parseFile(String path)
|
||||||
throws ParserConfigurationException, IOException, SAXException, IllegalArgumentException;
|
throws ParserConfigurationException, IOException, SAXException, IllegalArgumentException;
|
||||||
|
|
||||||
public abstract List<Shape> getShapes();
|
public abstract List<List<Shape>> getShapes();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package parser;
|
||||||
|
|
||||||
|
import engine.Camera;
|
||||||
|
import engine.Vector3;
|
||||||
|
import engine.WorldObject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import shapes.Shape;
|
||||||
|
import shapes.Shapes;
|
||||||
|
|
||||||
|
public class ObjParser extends FileParser {
|
||||||
|
|
||||||
|
private static double OBJ_ROTATE_SPEED = Math.PI / 1000;
|
||||||
|
|
||||||
|
private List<List<Shape>> shapes;
|
||||||
|
|
||||||
|
private final float rotateSpeed;
|
||||||
|
private final float cameraX;
|
||||||
|
private final float cameraY;
|
||||||
|
private final float cameraZ;
|
||||||
|
private final float focalLength;
|
||||||
|
private final boolean isDefaultPosition;
|
||||||
|
|
||||||
|
public ObjParser(String path, float rotateSpeed, float cameraX, float cameraY, float cameraZ,
|
||||||
|
float focalLength, boolean isDefaultPosition) throws IOException {
|
||||||
|
checkFileExtension(path);
|
||||||
|
shapes = new ArrayList<>();
|
||||||
|
this.rotateSpeed = rotateSpeed;
|
||||||
|
this.cameraX = cameraX;
|
||||||
|
this.cameraY = cameraY;
|
||||||
|
this.cameraZ = cameraZ;
|
||||||
|
this.focalLength = focalLength;
|
||||||
|
this.isDefaultPosition = isDefaultPosition;
|
||||||
|
parseFile(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFileExtension() {
|
||||||
|
return "obj";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseFile(String path) throws IllegalArgumentException, IOException {
|
||||||
|
OBJ_ROTATE_SPEED *= rotateSpeed;
|
||||||
|
|
||||||
|
Vector3 cameraPos = new Vector3(cameraX, cameraY, cameraZ);
|
||||||
|
WorldObject object = new WorldObject(path);
|
||||||
|
|
||||||
|
// If camera position arguments haven't been specified, automatically work out the position of
|
||||||
|
// the camera based on the size of the object in the camera's view.
|
||||||
|
Camera camera = isDefaultPosition ? new Camera(focalLength, object)
|
||||||
|
: new Camera(focalLength, cameraPos);
|
||||||
|
|
||||||
|
Vector3 rotation = new Vector3(0, OBJ_ROTATE_SPEED, OBJ_ROTATE_SPEED);
|
||||||
|
|
||||||
|
shapes = preRender(object, rotation, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<List<Shape>> getShapes() {
|
||||||
|
return shapes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<List<Shape>> preRender(WorldObject object, Vector3 rotation,
|
||||||
|
Camera camera) {
|
||||||
|
List<List<Shape>> preRenderedFrames = new ArrayList<>();
|
||||||
|
// Number of frames it will take to render a full rotation of the object.
|
||||||
|
int numFrames = (int) (2 * Math.PI / OBJ_ROTATE_SPEED);
|
||||||
|
|
||||||
|
for (int i = 0; i < numFrames; i++) {
|
||||||
|
preRenderedFrames.add(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomicInteger renderedFrames = new AtomicInteger();
|
||||||
|
|
||||||
|
// pre-renders the WorldObject in parallel
|
||||||
|
IntStream.range(0, numFrames).parallel().forEach((frameNum) -> {
|
||||||
|
WorldObject clone = object.clone();
|
||||||
|
clone.rotate(rotation.scale(frameNum));
|
||||||
|
// Finds all lines to draw the object from the camera's view and then 'sorts' them by finding
|
||||||
|
// a hamiltonian path, which dramatically helps with rendering a clean image.
|
||||||
|
preRenderedFrames.set(frameNum, Shapes.sortLines(camera.draw(clone)));
|
||||||
|
int numRendered = renderedFrames.getAndIncrement();
|
||||||
|
|
||||||
|
if (numRendered % 50 == 0) {
|
||||||
|
System.out.println("Rendered " + numRendered + " frames of " + (numFrames + 1) + " total");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return preRenderedFrames;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,6 @@ import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
@ -31,11 +30,6 @@ public class SvgParser extends FileParser {
|
||||||
private final List<Shape> shapes;
|
private final List<Shape> shapes;
|
||||||
private final Map<Character, Function<List<Float>, List<? extends Shape>>> commandMap;
|
private final Map<Character, Function<List<Float>, List<? extends Shape>>> commandMap;
|
||||||
|
|
||||||
private float viewBoxWidth;
|
|
||||||
private float viewBoxHeight;
|
|
||||||
private float width;
|
|
||||||
private float height;
|
|
||||||
|
|
||||||
private Vector2 currPoint;
|
private Vector2 currPoint;
|
||||||
private Vector2 initialPoint;
|
private Vector2 initialPoint;
|
||||||
private Vector2 prevCubicControlPoint;
|
private Vector2 prevCubicControlPoint;
|
||||||
|
@ -119,20 +113,6 @@ public class SvgParser extends FileParser {
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the width and height of the viewBox attribute
|
|
||||||
private void getSvgDimensions(Node svgElem) {
|
|
||||||
List<Float> viewBox = Arrays.stream(getNodeValue(svgElem, "viewBox").split(" "))
|
|
||||||
.map(Float::parseFloat)
|
|
||||||
.skip(2)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
viewBoxWidth = viewBox.get(0);
|
|
||||||
viewBoxHeight = viewBox.get(1);
|
|
||||||
|
|
||||||
width = Float.parseFloat(getNodeValue(svgElem, "width"));
|
|
||||||
height = Float.parseFloat(getNodeValue(svgElem, "height"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Float> splitCommand(String command) {
|
private static List<Float> splitCommand(String command) {
|
||||||
List<Float> nums = new ArrayList<>();
|
List<Float> nums = new ArrayList<>();
|
||||||
String[] decimalSplit = command.split("\\.");
|
String[] decimalSplit = command.split("\\.");
|
||||||
|
@ -156,7 +136,7 @@ public class SvgParser extends FileParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFileExtension() {
|
protected String getFileExtension() {
|
||||||
return "svg";
|
return "svg";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,8 +150,6 @@ public class SvgParser extends FileParser {
|
||||||
throw new IllegalArgumentException("SVG has either zero or more than one svg element.");
|
throw new IllegalArgumentException("SVG has either zero or more than one svg element.");
|
||||||
}
|
}
|
||||||
|
|
||||||
getSvgDimensions(svgElem.get(0));
|
|
||||||
|
|
||||||
// Get all d attributes within path elements in the SVG file.
|
// Get all d attributes within path elements in the SVG file.
|
||||||
for (String path : getSvgPathAttributes(svg)) {
|
for (String path : getSvgPathAttributes(svg)) {
|
||||||
currPoint = new Vector2();
|
currPoint = new Vector2();
|
||||||
|
@ -206,8 +184,10 @@ public class SvgParser extends FileParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Shape> getShapes() {
|
public List<List<Shape>> getShapes() {
|
||||||
return shapes;
|
List<List<Shape>> frames = new ArrayList<>();
|
||||||
|
frames.add(shapes);
|
||||||
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses moveto commands (M and m commands)
|
// Parses moveto commands (M and m commands)
|
||||||
|
|
|
@ -17,28 +17,32 @@ public class Shapes {
|
||||||
|
|
||||||
// Normalises shapes between the coords -1 and 1 for proper scaling on an oscilloscope. May not
|
// Normalises shapes between the coords -1 and 1 for proper scaling on an oscilloscope. May not
|
||||||
// work perfectly with curves that heavily deviate from their start and end points.
|
// work perfectly with curves that heavily deviate from their start and end points.
|
||||||
public static List<Shape> normalizeShapes(List<Shape> shapes) {
|
public static List<List<Shape>> normalize(List<List<Shape>> shapeLists) {
|
||||||
double maxVertex = 0;
|
double maxVertex = 0;
|
||||||
|
|
||||||
for (Shape shape : shapes) {
|
for (List<Shape> shapes : shapeLists) {
|
||||||
Vector2 startVector = shape.nextVector(0);
|
for (Shape shape : shapes) {
|
||||||
Vector2 endVector = shape.nextVector(1);
|
Vector2 startVector = shape.nextVector(0);
|
||||||
|
Vector2 endVector = shape.nextVector(1);
|
||||||
|
|
||||||
double maxX = Math.max(Math.abs(startVector.getX()), Math.abs(endVector.getX()));
|
double maxX = Math.max(Math.abs(startVector.getX()), Math.abs(endVector.getX()));
|
||||||
double maxY = Math.max(Math.abs(startVector.getY()), Math.abs(endVector.getY()));
|
double maxY = Math.max(Math.abs(startVector.getY()), Math.abs(endVector.getY()));
|
||||||
|
|
||||||
maxVertex = Math.max(Math.max(maxX, maxY), maxVertex);
|
maxVertex = Math.max(Math.max(maxX, maxY), maxVertex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double factor = 2 / maxVertex;
|
double factor = 2 / maxVertex;
|
||||||
|
|
||||||
for (int i = 0; i < shapes.size(); i++) {
|
for (List<Shape> shapes : shapeLists) {
|
||||||
shapes.set(i, shapes.get(i)
|
for (int i = 0; i < shapes.size(); i++) {
|
||||||
.scale(new Vector2(factor, -factor))
|
shapes.set(i, shapes.get(i)
|
||||||
.translate(new Vector2(-1, 1)));
|
.scale(new Vector2(factor, -factor))
|
||||||
|
.translate(new Vector2(-1, 1)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return shapes;
|
return shapeLists;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Shape> generatePolygram(int sides, int angleJump, Vector2 start,
|
public static List<Shape> generatePolygram(int sides, int angleJump, Vector2 start,
|
||||||
|
|
|
@ -11,35 +11,35 @@ import shapes.Shape;
|
||||||
|
|
||||||
public class SvgParserTest {
|
public class SvgParserTest {
|
||||||
|
|
||||||
|
private List<? extends Shape> getShapes(SvgParser parser) {
|
||||||
|
return parser.getShapes().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lineToGeneratesALineShape()
|
public void lineToGeneratesALineShape()
|
||||||
throws ParserConfigurationException, SAXException, IOException {
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
SvgParser svgParser = new SvgParser("test/images/line-to.svg");
|
SvgParser svgParser = new SvgParser("test/images/line-to.svg");
|
||||||
List<Shape> shapes = svgParser.getShapes();
|
assertEquals(getShapes(svgParser), Line.pathToLines(0.5, 0.5, 0.75, 1, 0, 0, 0.5, 0.5));
|
||||||
assertEquals(shapes, Line.pathToLines(0.5, 0.5, 0.75, 1, 0, 0, 0.5, 0.5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void horizontalLineToGeneratesAHorizontalLineShape()
|
public void horizontalLineToGeneratesAHorizontalLineShape()
|
||||||
throws ParserConfigurationException, SAXException, IOException {
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
SvgParser svgParser = new SvgParser("test/images/horizontal-line-to.svg");
|
SvgParser svgParser = new SvgParser("test/images/horizontal-line-to.svg");
|
||||||
List<Shape> shapes = svgParser.getShapes();
|
assertEquals(getShapes(svgParser), Line.pathToLines(0.5, 0.5, 0.75, 0.5, 0, 0.5, 0.5, 0.5));
|
||||||
assertEquals(shapes, Line.pathToLines(0.5, 0.5, 0.75, 0.5, 0, 0.5, 0.5, 0.5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void verticalLineToGeneratesAVerticalLineShape()
|
public void verticalLineToGeneratesAVerticalLineShape()
|
||||||
throws ParserConfigurationException, SAXException, IOException {
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
SvgParser svgParser = new SvgParser("test/images/vertical-line-to.svg");
|
SvgParser svgParser = new SvgParser("test/images/vertical-line-to.svg");
|
||||||
List<Shape> shapes = svgParser.getShapes();
|
assertEquals(getShapes(svgParser), Line.pathToLines(0.5, 0.5, 0.5, 0.75, 0.5, 0, 0.5, 0.5));
|
||||||
assertEquals(shapes, Line.pathToLines(0.5, 0.5, 0.5, 0.75, 0.5, 0, 0.5, 0.5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void closingASubPathDrawsLineToInitialPoint()
|
public void closingASubPathDrawsLineToInitialPoint()
|
||||||
throws ParserConfigurationException, SAXException, IOException {
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
SvgParser svgParser = new SvgParser("test/images/closing-subpath.svg");
|
SvgParser svgParser = new SvgParser("test/images/closing-subpath.svg");
|
||||||
List<Shape> shapes = svgParser.getShapes();
|
assertEquals(getShapes(svgParser), Line.pathToLines(0.5, 0.5, 0.75, 0.5, 0.75, 0.75, 0.5, 0.75, 0.5, 0.5));
|
||||||
assertEquals(shapes, Line.pathToLines(0.5, 0.5, 0.75, 0.5, 0.75, 0.75, 0.5, 0.75, 0.5, 0.5));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue