From 0b0c6abebd0367701afc764feb0e407b3e919a0f Mon Sep 17 00:00:00 2001 From: fabianterhorst Date: Thu, 6 Apr 2017 19:32:13 +0200 Subject: [PATCH] * performance update * replace Double wrapper object with double and nullable with another method * improve sort algorithm * reduce object allocations * point now takes doubles instead of the Double wrapper object * add 2 new scale methods instead of nullable parameters --- .../screenshot/IsometricViewTest.java | 8 +- .../fabianterhorst/isometric/Isometric.java | 196 ++++++++++-------- .../io/fabianterhorst/isometric/Path.java | 19 +- .../io/fabianterhorst/isometric/Point.java | 28 ++- .../io/fabianterhorst/isometric/Shape.java | 46 +++- .../fabianterhorst/isometric/shapes/Knot.java | 2 +- .../isometric/shapes/Octahedron.java | 2 +- 7 files changed, 187 insertions(+), 114 deletions(-) diff --git a/lib/src/androidTest/java/io/fabianterhorst/isometric/screenshot/IsometricViewTest.java b/lib/src/androidTest/java/io/fabianterhorst/isometric/screenshot/IsometricViewTest.java index a4744bc..baec8f9 100644 --- a/lib/src/androidTest/java/io/fabianterhorst/isometric/screenshot/IsometricViewTest.java +++ b/lib/src/androidTest/java/io/fabianterhorst/isometric/screenshot/IsometricViewTest.java @@ -193,10 +193,10 @@ public void sampleThree(double angle, IsometricView isometricView) { isometricView.add(new Prism(new Point(3, 0, 2), 2, 4, 1), new Color(33, 150, 243)); isometricView.add(new Prism(new Point(2, 1, 2), 1, 3, 1), new Color(33, 150, 243)); isometricView.add(new Stairs(new Point(2, 0, 2), 10).rotateZ(new Point(2.5, 0.5, 0), -Math.PI / 2), new Color(33, 150, 243)); - isometricView.add(new Pyramid(new Point(2, 3, 3)).scale(new Point(2, 4, 3), 0.5, null, null), new Color(180, 180, 0)); - isometricView.add(new Pyramid(new Point(4, 3, 3)).scale(new Point(5, 4, 3), 0.5, null, null), new Color(180, 0, 180)); - isometricView.add(new Pyramid(new Point(4, 1, 3)).scale(new Point(5, 1, 3), 0.5, null, null), new Color(0, 180, 180)); - isometricView.add(new Pyramid(new Point(2, 1, 3)).scale(new Point(2, 1, 3), 0.5, null, null), new Color(40, 180, 40)); + isometricView.add(new Pyramid(new Point(2, 3, 3)).scale(new Point(2, 4, 3), 0.5), new Color(180, 180, 0)); + isometricView.add(new Pyramid(new Point(4, 3, 3)).scale(new Point(5, 4, 3), 0.5), new Color(180, 0, 180)); + isometricView.add(new Pyramid(new Point(4, 1, 3)).scale(new Point(5, 1, 3), 0.5), new Color(0, 180, 180)); + isometricView.add(new Pyramid(new Point(2, 1, 3)).scale(new Point(2, 1, 3), 0.5), new Color(40, 180, 40)); isometricView.add(new Prism(new Point(3, 2, 3), 1, 1, 0.2), new Color(50, 50, 50)); isometricView.add(new Octahedron(new Point(3, 2, 3.2)).rotateZ(new Point(3.5, 2.5, 0), angle), new Color(0, 180, 180)); } diff --git a/lib/src/main/java/io/fabianterhorst/isometric/Isometric.java b/lib/src/main/java/io/fabianterhorst/isometric/Isometric.java index 3787315..ac0bf24 100644 --- a/lib/src/main/java/io/fabianterhorst/isometric/Isometric.java +++ b/lib/src/main/java/io/fabianterhorst/isometric/Isometric.java @@ -51,17 +51,9 @@ public Isometric() { * Y rides perpendicular to this angle (in isometric view: PI - angle) * Z affects the y coordinate of the drawn point */ - //Todo: use less object creation and maybe reuse the point public Point translatePoint(Point point) { - Point xMap = new Point(point.x * this.transformation[0][0], - point.x * this.transformation[0][1]); - - Point yMap = new Point(point.y * this.transformation[1][0], - point.y * this.transformation[1][1]); - - double x = this.originX + xMap.x + yMap.x; - double y = this.originY - xMap.y - yMap.y - (point.z * this.scale); - return new Point(x, y); + return new Point(this.originX + point.x * this.transformation[0][0] + point.y * this.transformation[1][0], + this.originY - point.x * this.transformation[0][1] - point.y * this.transformation[1][1] - (point.z * this.scale)); } public void add(Path path, Color color) { @@ -121,13 +113,12 @@ public void measure(int width, int height, boolean sort) { item.transformedPoints.add(translatePoint(point)); } - item.drawPath.moveTo(item.transformedPoints.get(0).x.floatValue(), item.transformedPoints.get(0).y.floatValue()); + item.drawPath.moveTo((float) item.transformedPoints.get(0).x, (float) item.transformedPoints.get(0).y); for (int i = 1, length = item.transformedPoints.size(); i < length; i++) { - item.drawPath.lineTo(item.transformedPoints.get(i).x.floatValue(), item.transformedPoints.get(i).y.floatValue()); + item.drawPath.lineTo((float) item.transformedPoints.get(i).x, (float) item.transformedPoints.get(i).y); } - //Todo: check if needed item.drawPath.close(); } @@ -136,7 +127,6 @@ public void measure(int width, int height, boolean sort) { } } - private List sortPaths() { ArrayList sortedItems = new ArrayList<>(); Point observer = new Point(-10, -10, 20); @@ -145,10 +135,14 @@ private List sortPaths() { for (int i = 0; i < length; i++) { drawBefore.add(i, new ArrayList()); } + Item itemA; + Item itemB; for (int i = 0; i < length; i++) { + itemA = items.get(i); for (int j = 0; j < i; j++) { - if (hasIntersection(items.get(i).transformedPoints, items.get(j).transformedPoints)) { - int cmpPath = items.get(i).path.closerThan(items.get(j).path, observer); + itemB = items.get(j); + if (hasIntersection(itemA.transformedPoints, itemB.transformedPoints)) { + int cmpPath = itemA.path.closerThan(itemB.path, observer); if (cmpPath < 0) { drawBefore.get(i).add(drawBefore.get(i).size(), j); } @@ -158,6 +152,7 @@ private List sortPaths() { } } } + Item currItem; int drawThisTurn = 1; while (drawThisTurn == 1) { drawThisTurn = 0; @@ -170,11 +165,9 @@ private List sortPaths() { } } if (canDraw == 1) { - Item item = new Item(items.get(i).path, items.get(i).baseColor); - item.drawPath = items.get(i).drawPath; - item.transformedPoints = items.get(i).transformedPoints; + currItem = items.get(i); + Item item = new Item(currItem); sortedItems.add(item); - Item currItem = items.get(i); currItem.drawn = 1; items.set(i, currItem); drawThisTurn = 1; @@ -182,12 +175,11 @@ private List sortPaths() { } } } + for (int i = 0; i < length; i++) { - if (items.get(i).drawn == 0) { - Item item = new Item(items.get(i).path, items.get(i).baseColor); - item.drawPath = items.get(i).drawPath; - item.transformedPoints = items.get(i).transformedPoints; - sortedItems.add(item); + currItem = items.get(i); + if (currItem.drawn == 0) { + sortedItems.add(new Item(currItem)); } } return sortedItems; @@ -204,6 +196,8 @@ public void draw(Canvas canvas) { } } + //Todo: use android.grphics region object to check if point is inside region + //Todo: use path.op to check if the path intersects with another path @Nullable public Item findItemForPosition(Point position) { //Todo: reverse sorting for click detection, because hidden object is getting drawed first und will be returned as the first as well @@ -256,29 +250,29 @@ public Item findItemForPosition(Point position) { //search for equal points that are above or below for left and right or left and right for bottom and top for (Point point : item.transformedPoints) { - if (point.x.equals(left.x)) { - if (!point.y.equals(left.y)) { + if (point.x == left.x) { + if (point.y != left.y) { items.add(point); } } - if (point.x.equals(right.x)) { - if (!point.y.equals(right.y)) { + if (point.x == right.x) { + if (point.y != right.y) { items.add(point); } } - if (point.y.equals(top.y)) { - if (!point.y.equals(top.y)) { + if (point.y == top.y) { + if (point.y != top.y) { items.add(point); } } - if (point.y.equals(bottom.y)) { - if (!point.y.equals(bottom.y)) { + if (point.y == bottom.y) { + if (point.y != bottom.y) { items.add(point); } } } - if (isPointInPoly(items, position)) { + if (isPointInPoly(items, position.x, position.y)) { return item; } } @@ -289,11 +283,23 @@ static class Item { Path path; Color baseColor; Paint paint; - int drawn = 0; - List transformedPoints = new ArrayList<>(); - android.graphics.Path drawPath = new android.graphics.Path(); + int drawn; + List transformedPoints; + android.graphics.Path drawPath; + + Item(Item item) { + transformedPoints = item.transformedPoints; + drawPath = item.drawPath; + drawn = item.drawn; + this.paint = item.paint; + this.path = item.path; + this.baseColor = item.baseColor; + } Item(Path path, Color baseColor) { + transformedPoints = new ArrayList<>(); + drawPath = new android.graphics.Path(); + drawn = 0; this.paint = new Paint(Paint.ANTI_ALIAS_FLAG); this.paint.setStyle(Paint.Style.FILL_AND_STROKE); this.paint.setStrokeWidth(1); @@ -303,11 +309,22 @@ static class Item { } } - private boolean isPointInPoly(List poly, Point pt) { + private boolean isPointInPoly(List poly, double x, double y) { boolean c = false; for (int i = -1, l = poly.size(), j = l - 1; ++i < l; j = i) { - if (((poly.get(i).y <= pt.y && pt.y < poly.get(j).y) || (poly.get(j).y <= pt.y && pt.y < poly.get(i).y)) - && (pt.x < (poly.get(j).x - poly.get(i).x) * (pt.y - poly.get(i).y) / (poly.get(j).y - poly.get(i).y) + poly.get(i).x)) { + if (((poly.get(i).y <= y && y < poly.get(j).y) || (poly.get(j).y <= y && y < poly.get(i).y)) + && (x < (poly.get(j).x - poly.get(i).x) * (y - poly.get(i).y) / (poly.get(j).y - poly.get(i).y) + poly.get(i).x)) { + c = !c; + } + } + return c; + } + + private boolean isPointInPoly(Point[] poly, double x, double y) { + boolean c = false; + for (int i = -1, l = poly.length, j = l - 1; ++i < l; j = i) { + if (((poly[i].y <= y && y < poly[j].y) || (poly[j].y <= y && y < poly[i].y)) + && (x < (poly[j].x - poly[i].x) * (y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x)) { c = !c; } } @@ -324,55 +341,64 @@ private boolean hasIntersection(List pointsA, List pointsB) { double BminY = pointsB.get(0).y; double BmaxX = BminX; double BmaxY = BminY; + + Point point; + for (i = 0; i < lengthA; i++) { - AminX = Math.min(AminX, pointsA.get(i).x); - AminY = Math.min(AminY, pointsA.get(i).y); - AmaxX = Math.max(AmaxX, pointsA.get(i).x); - AmaxY = Math.max(AmaxY, pointsA.get(i).y); + point = pointsA.get(i); + AminX = Math.min(AminX, point.x); + AminY = Math.min(AminY, point.y); + AmaxX = Math.max(AmaxX, point.x); + AmaxY = Math.max(AmaxY, point.y); } for (i = 0; i < lengthB; i++) { - BminX = Math.min(BminX, pointsB.get(i).x); - BminY = Math.min(BminY, pointsB.get(i).y); - BmaxX = Math.max(BmaxX, pointsB.get(i).x); - BmaxY = Math.max(BmaxY, pointsB.get(i).y); + point = pointsB.get(i); + BminX = Math.min(BminX, point.x); + BminY = Math.min(BminY, point.y); + BmaxX = Math.max(BmaxX, point.x); + BmaxY = Math.max(BmaxY, point.y); } if (((AminX <= BminX && BminX <= AmaxX) || (BminX <= AminX && AminX <= BmaxX)) && ((AminY <= BminY && BminY <= AmaxY) || (BminY <= AminY && AminY <= BmaxY))) { // now let's be more specific - List polyA = cloneList(pointsA); - List polyB = cloneList(pointsB); - polyA.add(pointsA.get(0)); - polyB.add(pointsB.get(0)); + Point[] polyA = cloneListAndInsert(pointsA, pointsA.get(0)); + Point[] polyB = cloneListAndInsert(pointsB, pointsB.get(0)); // see if edges cross, or one contained in the other - List deltaAX = new ArrayList<>(); - List deltaAY = new ArrayList<>(); - List deltaBX = new ArrayList<>(); - List deltaBY = new ArrayList<>(); - List rA = new ArrayList<>(); - List rB = new ArrayList<>(); - lengthPolyA = polyA.size(); + lengthPolyA = polyA.length; + lengthPolyB = polyB.length; + + double[] deltaAX = new double[lengthPolyA]; + double[] deltaAY = new double[lengthPolyA]; + double[] deltaBX = new double[lengthPolyB]; + double[] deltaBY = new double[lengthPolyB]; + + double[] rA = new double[lengthPolyA]; + double[] rB = new double[lengthPolyB]; + for (i = 0; i <= lengthPolyA - 2; i++) { - deltaAX.add(i, polyA.get(i + 1).x - polyA.get(i).x); - deltaAY.add(i, polyA.get(i + 1).y - polyA.get(i).y); + point = polyA[i]; + deltaAX[i] = polyA[i + 1].x - point.x; + deltaAY[i] = polyA[i + 1].y - point.y; //equation written as deltaY.x - deltaX.y + r = 0 - rA.add(i, deltaAX.get(i) * polyA.get(i).y - deltaAY.get(i) * polyA.get(i).x); + rA[i] = deltaAX[i] * point.y - deltaAY[i] * point.x; } - lengthPolyB = polyB.size(); + for (i = 0; i <= lengthPolyB - 2; i++) { - deltaBX.add(i, polyB.get(i + 1).x - polyB.get(i).x); - deltaBY.add(i, polyB.get(i + 1).y - polyB.get(i).y); - rB.add(i, deltaBX.get(i) * polyB.get(i).y - deltaBY.get(i) * polyB.get(i).x); + point = polyB[i]; + deltaBX[i] = polyB[i + 1].x - point.x; + deltaBY[i] = polyB[i + 1].y - point.y; + rB[i] = deltaBX[i] * point.y - deltaBY[i] * point.x; } for (i = 0; i <= lengthPolyA - 2; i++) { for (j = 0; j <= lengthPolyB - 2; j++) { - if (deltaAX.get(i) * deltaBY.get(j) != deltaAY.get(i) * deltaBX.get(j)) { + if (deltaAX[i] * deltaBY[j] != deltaAY[i] * deltaBX[j]) { //case when vectors are colinear, or one polygon included in the other, is covered after //two segments cross each other if and only if the points of the first are on each side of the line defined by the second and vice-versa - if ((deltaAY.get(i) * polyB.get(j).x - deltaAX.get(i) * polyB.get(j).y + rA.get(i)) * (deltaAY.get(i) * polyB.get(j + 1).x - deltaAX.get(i) * polyB.get(j + 1).y + rA.get(i)) < -0.000000001 && - (deltaBY.get(j) * polyA.get(i).x - deltaBX.get(j) * polyA.get(i).y + rB.get(j)) * (deltaBY.get(j) * polyA.get(i + 1).x - deltaBX.get(j) * polyA.get(i + 1).y + rB.get(j)) < -0.000000001) { + if ((deltaAY[i] * polyB[j].x - deltaAX[i] * polyB[j].y + rA[i]) * (deltaAY[i] * polyB[j + 1].x - deltaAX[i] * polyB[j + 1].y + rA[i]) < -0.000000001 && + (deltaBY[j] * polyA[i].x - deltaBX[j] * polyA[i].y + rB[j]) * (deltaBY[j] * polyA[i + 1].x - deltaBX[j] * polyA[i + 1].y + rB[j]) < -0.000000001) { return true; } } @@ -380,12 +406,14 @@ private boolean hasIntersection(List pointsA, List pointsB) { } for (i = 0; i <= lengthPolyA - 2; i++) { - if (isPointInPoly(polyB, new Point(polyA.get(i).x, polyA.get(i).y))) { + point = polyA[i]; + if (isPointInPoly(polyB, point.x, point.y)) { return true; } } for (i = 0; i <= lengthPolyB - 2; i++) { - if (isPointInPoly(polyA, new Point(polyB.get(i).x, polyB.get(i).y))) { + point = polyB[i]; + if (isPointInPoly(polyA, point.x, point.y)) { return true; } } @@ -396,21 +424,19 @@ private boolean hasIntersection(List pointsA, List pointsB) { } } - private List cloneList(List points) { - List clonedList = new ArrayList<>(points.size()); - for (Point point : points) { - Point newPoint = new Point(); - if (point.x != null) { - newPoint.x = point.x; - } - if (point.y != null) { - newPoint.y = point.y; - } - if (point.z != null) { - newPoint.z = point.z; - } - clonedList.add(newPoint); + private Point[] cloneListAndInsert(List points, Point insertPoint) { + int size = points.size(); + Point[] clonedList = new Point[size + 1]; + Point point, newPoint; + for (int i = 0; i < size; i++) { + point = points.get(i); + newPoint = new Point(); + newPoint.x = point.x; + newPoint.y = point.y; + newPoint.z = point.z; + clonedList[i] = newPoint; } + clonedList[size] = insertPoint; return clonedList; } } diff --git a/lib/src/main/java/io/fabianterhorst/isometric/Path.java b/lib/src/main/java/io/fabianterhorst/isometric/Path.java index ba5dffc..959e279 100644 --- a/lib/src/main/java/io/fabianterhorst/isometric/Path.java +++ b/lib/src/main/java/io/fabianterhorst/isometric/Path.java @@ -10,6 +10,7 @@ public class Path { + //Todo: replace with Point[] final List points; public Path() { @@ -75,7 +76,7 @@ public Path rotateZ(Point origin, double angle) { return new Path(points); } - public Path scale(Point origin, Double dx, Double dy, Double dz) { + public Path scale(Point origin, double dx, double dy, double dz) { List points = new ArrayList<>(); for (Point point : this.points) { points.add(point.scale(origin, dx, dy, dz)); @@ -83,6 +84,22 @@ public Path scale(Point origin, Double dx, Double dy, Double dz) { return new Path(points); } + public Path scale(Point origin, double dx, double dy) { + List points = new ArrayList<>(); + for (Point point : this.points) { + points.add(point.scale(origin, dx, dy)); + } + return new Path(points); + } + + public Path scale(Point origin, double dx) { + List points = new ArrayList<>(); + for (Point point : this.points) { + points.add(point.scale(origin, dx)); + } + return new Path(points); + } + public double depth() { int i; double total = 0; diff --git a/lib/src/main/java/io/fabianterhorst/isometric/Point.java b/lib/src/main/java/io/fabianterhorst/isometric/Point.java index bc430d7..eb47001 100644 --- a/lib/src/main/java/io/fabianterhorst/isometric/Point.java +++ b/lib/src/main/java/io/fabianterhorst/isometric/Point.java @@ -1,7 +1,5 @@ package io.fabianterhorst.isometric; -import android.support.annotation.Nullable; - /** * Created by fabianterhorst on 31.03.17. */ @@ -10,7 +8,7 @@ public class Point { public static final Point ORIGIN = new Point(0, 0, 0); - protected Double x, y, z; + protected double x, y, z; Point() { @@ -27,15 +25,15 @@ public Point(double x, double y, double z) { this.z = z; } - public Double getX() { + public double getX() { return x; } - public Double getY() { + public double getY() { return y; } - public Double getZ() { + public double getZ() { return z; } @@ -52,22 +50,22 @@ public Point translate(double dx, double dy, double dz) { /** * Scale a point about a given origin */ - public Point scale(Point origin, @Nullable Double dx, @Nullable Double dy, @Nullable Double dz) { + public Point scale(Point origin, double dx, double dy, double dz) { Point p = this.translate(-origin.x, -origin.y, -origin.z); - if (dy == null && dz == null) { - /* If both dy and dz are left out, scale all coordinates equally */ - dy = dz = dx; - } else { - /* If just dz is missing, set it equal to 1 */ - dz = dz == null ? 1 : dz; - } - p.x *= dx; p.y *= dy; p.z *= dz; return p.translate(origin.x, origin.y, origin.z); } + public Point scale(Point origin, double dx) { + return scale(origin, dx, dx, dx); + } + + public Point scale(Point origin, double dx, double dy) { + return scale(origin, dx, dy, 1); + } + /** * Rotate about origin on the X axis */ diff --git a/lib/src/main/java/io/fabianterhorst/isometric/Shape.java b/lib/src/main/java/io/fabianterhorst/isometric/Shape.java index bf0e9cf..4899bc3 100644 --- a/lib/src/main/java/io/fabianterhorst/isometric/Shape.java +++ b/lib/src/main/java/io/fabianterhorst/isometric/Shape.java @@ -1,7 +1,5 @@ package io.fabianterhorst.isometric; -import android.support.annotation.Nullable; - import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -67,7 +65,7 @@ public Shape rotateZ(Point origin, double angle) { return new Shape(paths); } - public Shape scale(Point origin, Double dx, Double dy, Double dz) { + public Shape scale(Point origin, double dx, double dy, double dz) { List paths = new ArrayList<>(); for (Path path : this.paths) { paths.add(path.scale(origin, dx, dy, dz)); @@ -75,12 +73,40 @@ public Shape scale(Point origin, Double dx, Double dy, Double dz) { return new Shape(paths); } - public void scalePaths(Point origin, Double dx, Double dy, Double dz) { + public Shape scale(Point origin, double dx, double dy) { + List paths = new ArrayList<>(); + for (Path path : this.paths) { + paths.add(path.scale(origin, dx, dy)); + } + return new Shape(paths); + } + + public Shape scale(Point origin, double dx) { + List paths = new ArrayList<>(); + for (Path path : this.paths) { + paths.add(path.scale(origin, dx)); + } + return new Shape(paths); + } + + public void scalePaths(Point origin, double dx, double dy, double dz) { for (int i = 0, length = paths.size();i < length;i++) { paths.set(i, paths.get(i).scale(origin, dx, dy, dz)); } } + public void scalePaths(Point origin, double dx, double dy) { + for (int i = 0, length = paths.size();i < length;i++) { + paths.set(i, paths.get(i).scale(origin, dx, dy)); + } + } + + public void scalePaths(Point origin, double dx) { + for (int i = 0, length = paths.size();i < length;i++) { + paths.set(i, paths.get(i).scale(origin, dx)); + } + } + public void translatePaths(double dx, double dy, double dz) { for (int i = 0, length = paths.size();i < length;i++) { paths.set(i, paths.get(i).translate(dx, dy, dz)); @@ -101,13 +127,19 @@ public int compare(Path pathA, Path pathB) { return this.paths; } - public static Shape extrude(Path path, @Nullable Double height) { + public static Shape extrude(Path path) { + return extrude(new Shape(), path, 1); + } + + public static Shape extrude(Path path, double height) { return extrude(new Shape(), path, height); } - public static Shape extrude(Shape shape, Path path, @Nullable Double height) { - height = height != null ? height : 1; + public static Shape extrude(Shape shape, Path path) { + return extrude(shape, path, 1); + } + public static Shape extrude(Shape shape, Path path, double height) { Path topPath = path.translate(0, 0, height); int i; int length = path.points.size(); diff --git a/lib/src/main/java/io/fabianterhorst/isometric/shapes/Knot.java b/lib/src/main/java/io/fabianterhorst/isometric/shapes/Knot.java index 0fb9092..db582a9 100644 --- a/lib/src/main/java/io/fabianterhorst/isometric/shapes/Knot.java +++ b/lib/src/main/java/io/fabianterhorst/isometric/shapes/Knot.java @@ -17,7 +17,7 @@ public Knot(Point origin) { push(new Prism(new Point(4, 4, -2), 1, 1, 3).getPaths()); push(new Path(new Point[]{new Point(0, 0, 2), new Point(0, 0, 1), new Point(1, 0, 1), new Point(1, 0, 2)})); push(new Path(new Point[]{new Point(0, 0, 2), new Point(0, 1, 2), new Point(0, 1, 1), new Point(0, 0, 1)})); - scalePaths(Point.ORIGIN, 1.0 / 5.0, null, null); + scalePaths(Point.ORIGIN, 1.0 / 5.0); translatePaths(-0.1, 0.15, 0.4); translatePaths(origin.getX(), origin.getY(), origin.getZ()); } diff --git a/lib/src/main/java/io/fabianterhorst/isometric/shapes/Octahedron.java b/lib/src/main/java/io/fabianterhorst/isometric/shapes/Octahedron.java index 28627e4..f678788 100644 --- a/lib/src/main/java/io/fabianterhorst/isometric/shapes/Octahedron.java +++ b/lib/src/main/java/io/fabianterhorst/isometric/shapes/Octahedron.java @@ -19,6 +19,6 @@ public Octahedron(Point origin) { push(upperTriangle.rotateZ(center, i * Math.PI / 2.0)); push(lowerTriangle.rotateZ(center, i * Math.PI / 2.0)); } - scalePaths(center, Math.sqrt(2) / 2.0, Math.sqrt(2) / 2.0, 1.0); + scalePaths(center, Math.sqrt(2) / 2.0, Math.sqrt(2) / 2.0, 1); } }