kopia lustrzana https://github.com/jameshball/osci-render
Implemented 3D code from ICHack project
rodzic
a55f57163c
commit
ca9382d272
|
@ -2,7 +2,7 @@ package audio;
|
||||||
|
|
||||||
import shapes.Ellipse;
|
import shapes.Ellipse;
|
||||||
import shapes.Shapes;
|
import shapes.Shapes;
|
||||||
import shapes.Vector;
|
import shapes.Vector2;
|
||||||
|
|
||||||
public class AudioClient {
|
public class AudioClient {
|
||||||
private static final int SAMPLE_RATE = 192000;
|
private static final int SAMPLE_RATE = 192000;
|
||||||
|
@ -13,12 +13,20 @@ public class AudioClient {
|
||||||
AudioPlayer player = new AudioPlayer();
|
AudioPlayer player = new AudioPlayer();
|
||||||
AudioPlayer.FORMAT = AudioPlayer.defaultFormat(SAMPLE_RATE);
|
AudioPlayer.FORMAT = AudioPlayer.defaultFormat(SAMPLE_RATE);
|
||||||
|
|
||||||
AudioPlayer.addShapes(Shapes.generatePolygram(5, 3, 0.5, 60));
|
// AudioPlayer.addShapes(Shapes.generatePolygram(5, 3, 0.5, 60));
|
||||||
//AudioPlayer.addShapes(Shapes.generatePolygon(500, 0.5, 10));
|
//AudioPlayer.addShapes(Shapes.generatePolygon(500, 0.5, 10));
|
||||||
AudioPlayer.addShape(new Ellipse(0.5, 1));
|
// AudioPlayer.addShape(new Ellipse(0.5, 1));
|
||||||
|
|
||||||
|
// AudioPlayer.setRotateSpeed(0.8);
|
||||||
|
// AudioPlayer.setTranslation(2, new Vector(0.5, 0.5));
|
||||||
|
|
||||||
|
AudioPlayer.addShapes(Shapes.generatePolygon(4, new Vector2(0.25, 0.25)));
|
||||||
|
AudioPlayer.addShapes(Shapes.generatePolygon(4, new Vector2(0.5, 0.5)));
|
||||||
|
AudioPlayer.addShapes(Shapes.generatePolygon(4, new Vector2(-0.8, -0.8)));
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
AudioPlayer.addShape(new Ellipse(i / 10d, i / 10d));
|
||||||
|
}
|
||||||
|
|
||||||
AudioPlayer.setRotateSpeed(0.8);
|
|
||||||
AudioPlayer.setTranslation(2, new Vector(0.5, 0.5));
|
|
||||||
AudioPlayer.setScale(0.5);
|
AudioPlayer.setScale(0.5);
|
||||||
|
|
||||||
player.start();
|
player.start();
|
||||||
|
|
|
@ -2,7 +2,7 @@ package audio;
|
||||||
|
|
||||||
import com.xtaudio.xt.*;
|
import com.xtaudio.xt.*;
|
||||||
import shapes.Shape;
|
import shapes.Shape;
|
||||||
import shapes.Vector;
|
import shapes.Vector2;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -17,7 +17,7 @@ public class AudioPlayer extends Thread {
|
||||||
|
|
||||||
public static XtFormat FORMAT;
|
public static XtFormat FORMAT;
|
||||||
private static double TRANSLATE_SPEED = 0;
|
private static double TRANSLATE_SPEED = 0;
|
||||||
private static Vector TRANSLATE_VECTOR;
|
private static Vector2 TRANSLATE_VECTOR;
|
||||||
private static final int TRANSLATE_PHASE_INDEX = 0;
|
private static final int TRANSLATE_PHASE_INDEX = 0;
|
||||||
private static double ROTATE_SPEED = 0.4;
|
private static double ROTATE_SPEED = 0.4;
|
||||||
private static final int ROTATE_PHASE_INDEX = 1;
|
private static final int ROTATE_PHASE_INDEX = 1;
|
||||||
|
@ -81,7 +81,7 @@ public class AudioPlayer extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Shape translate(Shape shape, double sampleRate) {
|
private static Shape translate(Shape shape, double sampleRate) {
|
||||||
if (TRANSLATE_SPEED != 0 && !TRANSLATE_VECTOR.equals(new Vector())) {
|
if (TRANSLATE_SPEED != 0 && !TRANSLATE_VECTOR.equals(new Vector2())) {
|
||||||
return shape.translate(TRANSLATE_VECTOR.scale(
|
return shape.translate(TRANSLATE_VECTOR.scale(
|
||||||
Math.sin(nextTheta(sampleRate, TRANSLATE_SPEED, ROTATE_PHASE_INDEX))
|
Math.sin(nextTheta(sampleRate, TRANSLATE_SPEED, ROTATE_PHASE_INDEX))
|
||||||
));
|
));
|
||||||
|
@ -110,7 +110,7 @@ public class AudioPlayer extends Thread {
|
||||||
AudioPlayer.ROTATE_SPEED = speed;
|
AudioPlayer.ROTATE_SPEED = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setTranslation(double speed, Vector translation) {
|
public static void setTranslation(double speed, Vector2 translation) {
|
||||||
AudioPlayer.TRANSLATE_SPEED = speed;
|
AudioPlayer.TRANSLATE_SPEED = speed;
|
||||||
AudioPlayer.TRANSLATE_VECTOR = translation;
|
AudioPlayer.TRANSLATE_VECTOR = translation;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package engine;
|
||||||
|
|
||||||
|
import shapes.Line;
|
||||||
|
import shapes.Vector2;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Camera extends Renderer{
|
||||||
|
|
||||||
|
// position at 0,0,0,0
|
||||||
|
// rotation towards positive z axis
|
||||||
|
|
||||||
|
private double focalLength;
|
||||||
|
private double clipping = 0.001;
|
||||||
|
private Vector3 position;
|
||||||
|
private double fov;
|
||||||
|
|
||||||
|
public Camera() {
|
||||||
|
this.focalLength = 0.6;
|
||||||
|
this.position = new Vector3(0,0,-2);
|
||||||
|
this.fov = 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Line> draw(WorldObject worldObject) {
|
||||||
|
List<Vector2> vertices = new ArrayList<>();
|
||||||
|
for(Vector3 vertex : worldObject.getVertices()) {
|
||||||
|
vertices.add(this.project(vertex));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getFrame(vertices, worldObject.getEdgeData());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 project(Vector3 vertex) {
|
||||||
|
if(vertex.getZ() - this.position.getZ() < clipping) {
|
||||||
|
return new Vector2(0, 0);
|
||||||
|
}
|
||||||
|
return new Vector2(
|
||||||
|
vertex.getX() * focalLength / (vertex.getZ() - this.position.getZ()) + this.position.getX(),
|
||||||
|
vertex.getY() * focalLength / (vertex.getZ() - this.position.getZ()) + this.position.getY()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package engine;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
Camera camera = new Camera();
|
||||||
|
|
||||||
|
WorldObject cube = new WorldObject("resources/machine.obj", new Vector3(0,0,0), new Vector3());
|
||||||
|
while(true) {
|
||||||
|
camera.draw(cube);
|
||||||
|
cube.rotate(new Vector3(
|
||||||
|
0,
|
||||||
|
Math.PI / 100,
|
||||||
|
0
|
||||||
|
));
|
||||||
|
Thread.sleep(1000/30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package engine;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.regex.MatchResult;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Mesh {
|
||||||
|
|
||||||
|
private static final String VERTEX_PATTERN = "(?m)^v .*";
|
||||||
|
private static final String FACE_PATTERN = "(?m)^f .*";
|
||||||
|
|
||||||
|
private List<Vector3> vertices;
|
||||||
|
private List<Integer> edgeData;
|
||||||
|
|
||||||
|
public Mesh() {
|
||||||
|
this.vertices = new ArrayList<>();
|
||||||
|
this.edgeData = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mesh(List<Vector3> vertices, List<Integer> edgeData) {
|
||||||
|
this.vertices = vertices;
|
||||||
|
this.edgeData = edgeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Vector3> getVertices() {
|
||||||
|
return vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getEdgeData() {
|
||||||
|
return edgeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Mesh loadFromFile(String filename) {
|
||||||
|
Scanner sc;
|
||||||
|
try {
|
||||||
|
sc = new Scanner(new File(filename));
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Cannot load mesh data from: " + filename);
|
||||||
|
return new Mesh();
|
||||||
|
}
|
||||||
|
// load vertices
|
||||||
|
List<Vector3> vertices =
|
||||||
|
sc.findAll(VERTEX_PATTERN)
|
||||||
|
.map(s -> parseVertex(s.group(0)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// load edge data
|
||||||
|
List<Integer> edgeData = new ArrayList<>();
|
||||||
|
for(MatchResult result : sc.findAll(FACE_PATTERN).collect(Collectors.toList())) {
|
||||||
|
List<Integer> indices = parseFace(result.group(0));
|
||||||
|
for(int i = 0; i < indices.size(); i++ ) {
|
||||||
|
edgeData.add(indices.get(i));
|
||||||
|
edgeData.add(indices.get((i + 1) % indices.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Mesh(vertices, edgeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector3 parseVertex(String data) {
|
||||||
|
String[] coords = data.split(" ");
|
||||||
|
double x = Double.parseDouble(coords[1]);
|
||||||
|
double y = Double.parseDouble(coords[2]);
|
||||||
|
double z = Double.parseDouble(coords[3]);
|
||||||
|
return new Vector3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Integer> parseFace(String data) {
|
||||||
|
List<Integer> indices = new ArrayList<>();
|
||||||
|
String[] datas = data.split(" ");
|
||||||
|
for(int i = 1; i < datas.length; i++) {
|
||||||
|
indices.add(Integer.parseInt(datas[i].split("/")[0]) - 1);
|
||||||
|
}
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package engine;
|
||||||
|
|
||||||
|
import shapes.Line;
|
||||||
|
import shapes.Vector2;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class Renderer {
|
||||||
|
public List<Line> getFrame(List<Vector2> vertices, List<Integer> connections) {
|
||||||
|
List<Line> lines = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < connections.size(); i+=2) {
|
||||||
|
Vector2 start = vertices.get(connections.get(i));
|
||||||
|
Vector2 end = vertices.get(connections.get(i+1));
|
||||||
|
double x1 = start.getX();
|
||||||
|
double y1 = start.getY();
|
||||||
|
double x2 = end.getX();
|
||||||
|
double y2 = end.getY();
|
||||||
|
|
||||||
|
lines.add(new Line(x1, y1, x2, y2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package engine;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Vector3 {
|
||||||
|
private double x, y, z;
|
||||||
|
|
||||||
|
public Vector3() {
|
||||||
|
this.x = 0;
|
||||||
|
this.y = 0;
|
||||||
|
this.z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3(double x, double y, double z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 add(Vector3 other) {
|
||||||
|
return new Vector3(
|
||||||
|
this.getX() + other.getX(),
|
||||||
|
this.getY() + other.getY(),
|
||||||
|
this.getZ() + other.getZ()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 scale(double scalar) {
|
||||||
|
return new Vector3(
|
||||||
|
this.getX() * scalar,
|
||||||
|
this.getY() * scalar,
|
||||||
|
this.getZ() * scalar
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 rotateX(double delta) {
|
||||||
|
return new Vector3(
|
||||||
|
getX(),
|
||||||
|
Math.cos(delta) * getY() - Math.sin(delta) * getZ(),
|
||||||
|
Math.sin(delta) * getY() + Math.cos(delta) * getZ()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 rotateY(double delta) {
|
||||||
|
return new Vector3(
|
||||||
|
Math.cos(delta) * getX() + Math.sin(delta) * getZ(),
|
||||||
|
getY(),
|
||||||
|
-Math.sin(delta) * getX() + Math.cos(delta) * getZ()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 rotateZ(double delta) {
|
||||||
|
return new Vector3(
|
||||||
|
Math.cos(delta) * getX() - Math.sin(delta) * getY(),
|
||||||
|
Math.sin(delta) * getX() + Math.cos(delta) * getY(),
|
||||||
|
getZ()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 meanPoint(List<Vector3> points) {
|
||||||
|
Vector3 mean = new Vector3();
|
||||||
|
for(Vector3 point : points) {
|
||||||
|
mean = mean.add(point);
|
||||||
|
}
|
||||||
|
return mean.scale(1f / (points.size()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package engine;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class WorldObject {
|
||||||
|
|
||||||
|
private Mesh mesh;
|
||||||
|
private Vector3 position;
|
||||||
|
private Vector3 rotation;
|
||||||
|
|
||||||
|
public WorldObject(String filename, Vector3 position, Vector3 rotation) {
|
||||||
|
this.mesh = Mesh.loadFromFile(filename);
|
||||||
|
this.position = position;
|
||||||
|
this.rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotate(Vector3 theta) {
|
||||||
|
this.rotation = this.rotation.add(theta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Vector3> getVertices() {
|
||||||
|
List<Vector3> vertices = new ArrayList<>();
|
||||||
|
for(Vector3 vertex : mesh.getVertices()) {
|
||||||
|
vertices.add(
|
||||||
|
vertex
|
||||||
|
.rotateX(this.rotation.getX())
|
||||||
|
.rotateY(this.rotation.getY())
|
||||||
|
.rotateZ(this.rotation.getY())
|
||||||
|
.add(this.position));
|
||||||
|
}
|
||||||
|
return vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getEdgeData() {
|
||||||
|
return mesh.getEdgeData();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package graphs;
|
package graphs;
|
||||||
|
|
||||||
import shapes.Line;
|
import shapes.Line;
|
||||||
import shapes.Vector;
|
import shapes.Vector2;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -10,7 +10,7 @@ import java.util.Map;
|
||||||
// TODO: Implement Chinese postman solving.
|
// TODO: Implement Chinese postman solving.
|
||||||
|
|
||||||
public class Graph {
|
public class Graph {
|
||||||
private Map<Vector, Node> nodes;
|
private Map<Vector2, Node> nodes;
|
||||||
|
|
||||||
public Graph(List<Line> lines) {
|
public Graph(List<Line> lines) {
|
||||||
this.nodes = new HashMap<>();
|
this.nodes = new HashMap<>();
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
package graphs;
|
package graphs;
|
||||||
|
|
||||||
import shapes.Vector;
|
import shapes.Vector2;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Node {
|
public class Node {
|
||||||
private Vector location;
|
private Vector2 location;
|
||||||
private List<Node> adjacentNodes;
|
private List<Node> adjacentNodes;
|
||||||
private List<Double> adjacentWeights;
|
private List<Double> adjacentWeights;
|
||||||
|
|
||||||
public Node(Vector location) {
|
public Node(Vector2 location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.adjacentNodes = new ArrayList<>();
|
this.adjacentNodes = new ArrayList<>();
|
||||||
this.adjacentWeights = new ArrayList<>();
|
this.adjacentWeights = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector getLocation() {
|
public Vector2 getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@ public class Ellipse extends Shape {
|
||||||
private final double a;
|
private final double a;
|
||||||
private final double b;
|
private final double b;
|
||||||
private final double rotation;
|
private final double rotation;
|
||||||
private final Vector position;
|
private final Vector2 position;
|
||||||
|
|
||||||
public Ellipse(double a, double b, double weight, double rotation, Vector position) {
|
public Ellipse(double a, double b, double weight, double rotation, Vector2 position) {
|
||||||
this.a = a;
|
this.a = a;
|
||||||
this.b = b;
|
this.b = b;
|
||||||
this.weight = weight;
|
this.weight = weight;
|
||||||
|
@ -16,12 +16,12 @@ public class Ellipse extends Shape {
|
||||||
this.length = 2 * Math.PI * Math.sqrt((a * a + b * b) / 2);
|
this.length = 2 * Math.PI * Math.sqrt((a * a + b * b) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ellipse(double a, double b, Vector position) {
|
public Ellipse(double a, double b, Vector2 position) {
|
||||||
this(a, b, 100, 0, position);
|
this(a, b, 100, 0, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ellipse(double a, double b) {
|
public Ellipse(double a, double b) {
|
||||||
this(a, b, 100, 0, new Vector());
|
this(a, b, 100, 0, new Vector2());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,7 +53,7 @@ public class Ellipse extends Shape {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Shape translate(Vector vector) {
|
public Shape translate(Vector2 vector) {
|
||||||
return new Ellipse(a, b, weight, rotation, position.add(vector));
|
return new Ellipse(a, b, weight, rotation, position.add(vector));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
package shapes;
|
package shapes;
|
||||||
|
|
||||||
public class Line extends Shape {
|
public class Line extends Shape {
|
||||||
private final Vector a;
|
private final Vector2 a;
|
||||||
private final Vector b;
|
private final Vector2 b;
|
||||||
|
|
||||||
public static final double DEFAULT_WEIGHT = 100;
|
public static final double DEFAULT_WEIGHT = 100;
|
||||||
|
|
||||||
public Line(Vector a, Vector b, double weight) {
|
public Line(Vector2 a, Vector2 b, double weight) {
|
||||||
this.a = a;
|
this.a = a;
|
||||||
this.b = b;
|
this.b = b;
|
||||||
this.weight = weight;
|
this.weight = weight;
|
||||||
this.length = calculateLength();
|
this.length = calculateLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Line(Vector a, Vector b) {
|
public Line(Vector2 a, Vector2 b) {
|
||||||
this(a, b, DEFAULT_WEIGHT);
|
this(a, b, DEFAULT_WEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Line(double x1, double y1, double x2, double y2, double weight) {
|
public Line(double x1, double y1, double x2, double y2, double weight) {
|
||||||
this(new Vector(x1, y1), new Vector(x2, y2), weight);
|
this(new Vector2(x1, y1), new Vector2(x2, y2), weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Line(double x1, double y1, double x2, double y2) {
|
public Line(double x1, double y1, double x2, double y2) {
|
||||||
this(new Vector(x1, y1), new Vector(x2, y2));
|
this(new Vector2(x1, y1), new Vector2(x2, y2));
|
||||||
}
|
}
|
||||||
|
|
||||||
private double calculateLength() {
|
private double calculateLength() {
|
||||||
|
@ -35,7 +35,7 @@ public class Line extends Shape {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Line translate(Vector vector) {
|
public Line translate(Vector2 vector) {
|
||||||
return new Line(getA().add(vector), getB().add(vector));
|
return new Line(getA().add(vector), getB().add(vector));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,11 +58,11 @@ public class Line extends Shape {
|
||||||
return (float) (getY1() + (getY2() - getY1()) * drawingProgress);
|
return (float) (getY1() + (getY2() - getY1()) * drawingProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector getA() {
|
public Vector2 getA() {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector getB() {
|
public Vector2 getB() {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ public abstract class Shape {
|
||||||
public abstract float nextY(double drawingProgress);
|
public abstract float nextY(double drawingProgress);
|
||||||
public abstract Shape rotate(double theta);
|
public abstract Shape rotate(double theta);
|
||||||
public abstract Shape scale(double factor);
|
public abstract Shape scale(double factor);
|
||||||
public abstract Shape translate(Vector vector);
|
public abstract Shape translate(Vector2 vector);
|
||||||
|
|
||||||
public double getWeight() {
|
public double getWeight() {
|
||||||
return weight;
|
return weight;
|
||||||
|
|
|
@ -4,11 +4,11 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Shapes {
|
public class Shapes {
|
||||||
public static List<Shape> generatePolygram(int sides, int angleJump, Vector start, double weight) {
|
public static List<Shape> generatePolygram(int sides, int angleJump, Vector2 start, double weight) {
|
||||||
List<Shape> polygon = new ArrayList<>();
|
List<Shape> polygon = new ArrayList<>();
|
||||||
|
|
||||||
double theta = angleJump * 2 * Math.PI / sides;
|
double theta = angleJump * 2 * Math.PI / sides;
|
||||||
Vector rotated = start.rotate(theta);
|
Vector2 rotated = start.rotate(theta);
|
||||||
polygon.add(new Line(start, rotated, weight));
|
polygon.add(new Line(start, rotated, weight));
|
||||||
|
|
||||||
while (!rotated.equals(start)) {
|
while (!rotated.equals(start)) {
|
||||||
|
@ -20,32 +20,32 @@ public class Shapes {
|
||||||
return polygon;
|
return polygon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Shape> generatePolygram(int sides, int angleJump, Vector start) {
|
public static List<Shape> generatePolygram(int sides, int angleJump, Vector2 start) {
|
||||||
return generatePolygram(sides, angleJump, start, Line.DEFAULT_WEIGHT);
|
return generatePolygram(sides, angleJump, start, Line.DEFAULT_WEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Shape> generatePolygram(int sides, int angleJump, double scale, double weight) {
|
public static List<Shape> generatePolygram(int sides, int angleJump, double scale, double weight) {
|
||||||
return generatePolygram(sides, angleJump, new Vector(scale, scale), weight);
|
return generatePolygram(sides, angleJump, new Vector2(scale, scale), weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Shape> generatePolygram(int sides, int angleJump, double scale) {
|
public static List<Shape> generatePolygram(int sides, int angleJump, double scale) {
|
||||||
return generatePolygram(sides, angleJump, new Vector(scale, scale));
|
return generatePolygram(sides, angleJump, new Vector2(scale, scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Shape> generatePolygon(int sides, Vector start, double weight) {
|
public static List<Shape> generatePolygon(int sides, Vector2 start, double weight) {
|
||||||
return generatePolygram(sides, 1, start, weight);
|
return generatePolygram(sides, 1, start, weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Shape> generatePolygon(int sides, Vector start) {
|
public static List<Shape> generatePolygon(int sides, Vector2 start) {
|
||||||
return generatePolygram(sides, 1, start);
|
return generatePolygram(sides, 1, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Shape> generatePolygon(int sides, double scale, double weight) {
|
public static List<Shape> generatePolygon(int sides, double scale, double weight) {
|
||||||
return generatePolygon(sides, new Vector(scale, scale), weight);
|
return generatePolygon(sides, new Vector2(scale, scale), weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Shape> generatePolygon(int sides, double scale) {
|
public static List<Shape> generatePolygon(int sides, double scale) {
|
||||||
return generatePolygon(sides, new Vector(scale, scale));
|
return generatePolygon(sides, new Vector2(scale, scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Line> cleanupLines(List<Line> lines) {
|
public static List<Line> cleanupLines(List<Line> lines) {
|
||||||
|
|
|
@ -2,18 +2,18 @@ package shapes;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Vector {
|
public class Vector2 {
|
||||||
private final double x;
|
private final double x;
|
||||||
private final double y;
|
private final double y;
|
||||||
|
|
||||||
private static final double EPSILON = 0.001;
|
private static final double EPSILON = 0.001;
|
||||||
|
|
||||||
public Vector(double x, double y) {
|
public Vector2(double x, double y) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector() {
|
public Vector2() {
|
||||||
this(0, 0);
|
this(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,28 +25,28 @@ public class Vector {
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector setX(double x) {
|
public Vector2 setX(double x) {
|
||||||
return new Vector(x, this.y);
|
return new Vector2(x, this.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector setY(double y) {
|
public Vector2 setY(double y) {
|
||||||
return new Vector(this.x, y);
|
return new Vector2(this.x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector add(Vector vector) {
|
public Vector2 add(Vector2 vector) {
|
||||||
return new Vector(getX() + vector.getX(), getY() + vector.getY());
|
return new Vector2(getX() + vector.getX(), getY() + vector.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector scale(double factor) {
|
public Vector2 scale(double factor) {
|
||||||
return new Vector(getX() * factor, getY() * factor);
|
return new Vector2(getX() * factor, getY() * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == this) {
|
if (obj == this) {
|
||||||
return true;
|
return true;
|
||||||
} else if (obj instanceof Vector) {
|
} else if (obj instanceof Vector2) {
|
||||||
Vector vector = (Vector) obj;
|
Vector2 vector = (Vector2) obj;
|
||||||
|
|
||||||
return approxEquals(vector.getX(), getX()) && approxEquals(vector.getY(), getY());
|
return approxEquals(vector.getX(), getX()) && approxEquals(vector.getY(), getY());
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,12 +63,12 @@ public class Vector {
|
||||||
return Math.round(d * 1000) / 1000d;
|
return Math.round(d * 1000) / 1000d;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector copy() {
|
public Vector2 copy() {
|
||||||
return new Vector(x, y);
|
return new Vector2(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector rotate(double theta) {
|
public Vector2 rotate(double theta) {
|
||||||
Vector vector = setX(getX() * Math.cos(theta) - getY() * Math.sin(theta));
|
Vector2 vector = setX(getX() * Math.cos(theta) - getY() * Math.sin(theta));
|
||||||
vector = vector.setY(getX() * Math.sin(theta) + getY() * Math.cos(theta));
|
vector = vector.setY(getX() * Math.sin(theta) + getY() * Math.cos(theta));
|
||||||
|
|
||||||
return vector;
|
return vector;
|
Ładowanie…
Reference in New Issue