From ef63e47b94cbeb9fa0dc17382af7b19d9db27b9b Mon Sep 17 00:00:00 2001 From: James Ball Date: Thu, 5 Nov 2020 21:03:48 +0000 Subject: [PATCH] Add shape normalising function for correct rendering on oscilloscope --- src/audio/AudioClient.java | 11 +++++++++-- src/parser/SvgParser.java | 21 ++++++--------------- src/shapes/Shapes.java | 27 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/audio/AudioClient.java b/src/audio/AudioClient.java index 53a8d87..608805f 100644 --- a/src/audio/AudioClient.java +++ b/src/audio/AudioClient.java @@ -8,6 +8,9 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; +import javax.xml.parsers.ParserConfigurationException; +import org.xml.sax.SAXException; +import parser.SvgParser; import shapes.Shape; import shapes.Shapes; import shapes.Vector2; @@ -32,7 +35,8 @@ public class AudioClient { // // example: // osci-render models/cube.obj 3 - public static void main(String[] programArgs) throws IOException { + public static void main(String[] programArgs) + throws IOException, ParserConfigurationException, SAXException { // TODO: Calculate weight of lines using depth. // Reduce weight of lines drawn multiple times. // Find intersections of lines to (possibly) improve line cleanup. @@ -53,7 +57,10 @@ public class AudioClient { Vector3 rotation = new Vector3(0, OBJ_ROTATE_SPEED, OBJ_ROTATE_SPEED); System.out.println("Begin pre-render..."); - List> frames = preRender(object, rotation, camera); + //List> frames = preRender(object, rotation, camera); + List> frames = new ArrayList<>(); + List frame = Shapes.normalizeShapes(new SvgParser("test/images/sine-wave.svg").getShapes()); + frames.add(frame); System.out.println("Finish pre-render"); System.out.println("Connecting to audio player"); AudioPlayer player = new AudioPlayer(SAMPLE_RATE, frames, ROTATE_SPEED, TRANSLATION_SPEED, diff --git a/src/parser/SvgParser.java b/src/parser/SvgParser.java index dfa4af6..d8332bc 100644 --- a/src/parser/SvgParser.java +++ b/src/parser/SvgParser.java @@ -210,22 +210,13 @@ public class SvgParser extends FileParser { return shapes; } - private Vector2 scaledArguments(float arg1, float arg2) { - return new Vector2(arg1, arg2); -// return new Vector2(arg1, arg2) -// .scale(new Vector2((width / viewBoxWidth) / viewBoxWidth, -// -(height / viewBoxHeight) / viewBoxHeight) -// ).translate(new Vector2(-0.5, 0.5)) -// .scale(2); - } - // Parses moveto commands (M and m commands) private List parseMoveTo(List args, boolean isAbsolute) { if (args.size() % 2 != 0 || args.size() < 2) { throw new IllegalArgumentException("SVG moveto command has incorrect number of arguments."); } - Vector2 vec = scaledArguments(args.get(0), args.get(1)); + Vector2 vec = new Vector2(args.get(0), args.get(1)); if (isAbsolute) { currPoint = vec; @@ -273,9 +264,9 @@ public class SvgParser extends FileParser { Vector2 newPoint; if (expectedArgs == 1) { - newPoint = scaledArguments(args.get(i), args.get(i)); + newPoint = new Vector2(args.get(i), args.get(i)); } else { - newPoint = scaledArguments(args.get(i), args.get(i + 1)); + newPoint = new Vector2(args.get(i), args.get(i + 1)); } if (isHorizontal && !isVertical) { @@ -326,14 +317,14 @@ public class SvgParser extends FileParser { : prevQuadraticControlPoint.reflectRelativeToVector(currPoint); } } else { - controlPoint1 = scaledArguments(args.get(i), args.get(i + 1)); + controlPoint1 = new Vector2(args.get(i), args.get(i + 1)); } if (isCubic) { - controlPoint2 = scaledArguments(args.get(i + 2), args.get(i + 3)); + controlPoint2 = new Vector2(args.get(i + 2), args.get(i + 3)); } - Vector2 newPoint = scaledArguments(args.get(i + expectedArgs - 2), + Vector2 newPoint = new Vector2(args.get(i + expectedArgs - 2), args.get(i + expectedArgs - 1)); if (!isAbsolute) { diff --git a/src/shapes/Shapes.java b/src/shapes/Shapes.java index 1232612..bfdf141 100644 --- a/src/shapes/Shapes.java +++ b/src/shapes/Shapes.java @@ -12,8 +12,35 @@ import org.jgrapht.graph.AsSubgraph; import org.jgrapht.graph.DefaultUndirectedWeightedGraph; import org.jgrapht.graph.DefaultWeightedEdge; +// Helper functions for the Shape interface. public class Shapes { + // 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. + public static List normalizeShapes(List shapes) { + double maxVertex = 0; + + for (Shape shape : shapes) { + Vector2 startVector = shape.nextVector(0); + Vector2 endVector = shape.nextVector(1); + + double maxX = Math.max(Math.abs(startVector.getX()), Math.abs(endVector.getX())); + double maxY = Math.max(Math.abs(startVector.getY()), Math.abs(endVector.getY())); + + maxVertex = Math.max(Math.max(maxX, maxY), maxVertex); + } + + double factor = 2 / maxVertex; + + for (int i = 0; i < shapes.size(); i++) { + shapes.set(i, shapes.get(i) + .scale(new Vector2(factor, -factor)) + .translate(new Vector2(-1, 1))); + } + + return shapes; + } + public static List generatePolygram(int sides, int angleJump, Vector2 start, double weight) { List polygon = new ArrayList<>();