mirror of https://github.com/rusefi/jzy3d-api.git
Adding tests on Angle. Adding Permutations to generate all possible permutations of a set. Adding benchmark tools to prove that big and less polygon render faster than small and more
This commit is contained in:
parent
c89d189b22
commit
06921da699
|
@ -406,6 +406,13 @@ public class Chart {
|
||||||
getScene().getGraph().remove(drawable, updateViews);
|
getScene().getGraph().remove(drawable, updateViews);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void remove(List<? extends Drawable> drawables) {
|
||||||
|
for (Drawable drawable : drawables) {
|
||||||
|
remove(drawable, false);
|
||||||
|
}
|
||||||
|
getView().updateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
/* ADDING LIGHTS */
|
/* ADDING LIGHTS */
|
||||||
|
|
||||||
public Light addLight(Coord3d position) {
|
public Light addLight(Coord3d position) {
|
||||||
|
|
|
@ -12,27 +12,20 @@ import java.util.Random;
|
||||||
*/
|
*/
|
||||||
public class Color {
|
public class Color {
|
||||||
|
|
||||||
/** Black color. */
|
|
||||||
public static final Color BLACK = new Color(0.0f, 0.0f, 0.0f);
|
public static final Color BLACK = new Color(0.0f, 0.0f, 0.0f);
|
||||||
/** White color. */
|
|
||||||
public static final Color WHITE = new Color(1.0f, 1.0f, 1.0f);
|
public static final Color WHITE = new Color(1.0f, 1.0f, 1.0f);
|
||||||
/** Gray color. */
|
|
||||||
public static final Color GRAY = new Color(0.5f, 0.5f, 0.5f);
|
public static final Color GRAY = new Color(0.5f, 0.5f, 0.5f);
|
||||||
|
|
||||||
/** Red color. */
|
|
||||||
public static final Color RED = new Color(1.0f, 0.0f, 0.0f);
|
public static final Color RED = new Color(1.0f, 0.0f, 0.0f);
|
||||||
/** Green color. */
|
|
||||||
public static final Color GREEN = new Color(0.0f, 1.0f, 0.0f);
|
public static final Color GREEN = new Color(0.0f, 1.0f, 0.0f);
|
||||||
/** Blue color. */
|
|
||||||
public static final Color BLUE = new Color(0.0f, 0.0f, 1.0f);
|
public static final Color BLUE = new Color(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
/** Yellow color. */
|
|
||||||
public static final Color YELLOW = new Color(1.0f, 1.0f, 0.0f);
|
public static final Color YELLOW = new Color(1.0f, 1.0f, 0.0f);
|
||||||
/** Magenta color. */
|
|
||||||
public static final Color MAGENTA = new Color(1.0f, 0.0f, 1.0f);
|
public static final Color MAGENTA = new Color(1.0f, 0.0f, 1.0f);
|
||||||
/** Cyan color. */
|
|
||||||
public static final Color CYAN = new Color(0.0f, 1.0f, 1.0f);
|
public static final Color CYAN = new Color(0.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
public static final Color ORANGE = new Color(1.0f, 165.0f/255.0f, 0);
|
||||||
|
|
||||||
public static final Color[] COLORS = {RED, GREEN, BLUE, YELLOW, MAGENTA, CYAN};
|
public static final Color[] COLORS = {RED, GREEN, BLUE, YELLOW, MAGENTA, CYAN};
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
|
|
|
@ -1,10 +1,29 @@
|
||||||
package org.jzy3d.maths;
|
package org.jzy3d.maths;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.jzy3d.plot3d.primitives.Point;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Angle3d stores three 3d points, considering the angle is on the second one. An instance may
|
* An Angle3d stores three 3d points, considering the angle is on the second one. An instance may
|
||||||
* return angle(), cos() and sin().
|
* return angle(), cos() and sin().
|
||||||
*/
|
*/
|
||||||
public class Angle3d {
|
public class Angle3d {
|
||||||
|
public static final double DEGREE_90_D = Math.PI / 2;
|
||||||
|
public static final float DEGREE_90 = (float) DEGREE_90_D;
|
||||||
|
|
||||||
|
public static final double DEGREE_45_D = Math.PI / 4;
|
||||||
|
public static final float DEGREE_45 = (float) DEGREE_45_D;
|
||||||
|
|
||||||
|
protected float x1;
|
||||||
|
protected float x2;
|
||||||
|
protected float x3;
|
||||||
|
protected float y1;
|
||||||
|
protected float y2;
|
||||||
|
protected float y3;
|
||||||
|
protected float z1;
|
||||||
|
protected float z2;
|
||||||
|
protected float z3;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an angle, described by three points. The angle is supposed to be on p2
|
* Create an angle, described by three points. The angle is supposed to be on p2
|
||||||
|
@ -68,23 +87,96 @@ public class Angle3d {
|
||||||
|
|
||||||
/** Computes the angle at vertex p2 between rays p1,p2 and p3,p2. Returns 0 to PI radians. */
|
/** Computes the angle at vertex p2 between rays p1,p2 and p3,p2. Returns 0 to PI radians. */
|
||||||
public float angle() {
|
public float angle() {
|
||||||
|
return (float) angleD();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Computes the angle at vertex p2 between rays p1,p2 and p3,p2. Returns 0 to PI radians. */
|
||||||
|
public double angleD() {
|
||||||
double lenP1P3 = Math.sqrt(Math.pow(x1 - x3, 2) + Math.pow(y1 - y3, 2) + Math.pow(z1 - z3, 2));
|
double lenP1P3 = Math.sqrt(Math.pow(x1 - x3, 2) + Math.pow(y1 - y3, 2) + Math.pow(z1 - z3, 2));
|
||||||
double lenP1P2 = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + Math.pow(z1 - z2, 2));
|
double lenP1P2 = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + Math.pow(z1 - z2, 2));
|
||||||
double lenP3P2 = Math.sqrt(Math.pow(x3 - x2, 2) + Math.pow(y3 - y2, 2) + Math.pow(z3 - z2, 2));
|
double lenP3P2 = Math.sqrt(Math.pow(x3 - x2, 2) + Math.pow(y3 - y2, 2) + Math.pow(z3 - z2, 2));
|
||||||
double numerator = Math.pow(lenP1P2, 2) + Math.pow(lenP3P2, 2) - Math.pow(lenP1P3, 2);
|
double numerator = Math.pow(lenP1P2, 2) + Math.pow(lenP3P2, 2) - Math.pow(lenP1P3, 2);
|
||||||
double denominator = 2 * lenP1P2 * lenP3P2;
|
double denominator = 2 * lenP1P2 * lenP3P2;
|
||||||
return (float) Math.acos(numerator / denominator);
|
return Math.acos(numerator / denominator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************/
|
|
||||||
|
|
||||||
private float x1;
|
/**
|
||||||
private float x2;
|
* Compute the sum of all angles in the input coordinate list.
|
||||||
private float x3;
|
*
|
||||||
private float y1;
|
* If input contains point A, B, C, this method will compute angles ABC, BCA, CAB.
|
||||||
private float y2;
|
*
|
||||||
private float y3;
|
* An error is thrown if there are less than 3 points.
|
||||||
private float z1;
|
*
|
||||||
private float z2;
|
*
|
||||||
private float z3;
|
*
|
||||||
|
*/
|
||||||
|
public static double angleSum(List<Coord3d> coords) {
|
||||||
|
if(coords.size()<3) {
|
||||||
|
throw new IllegalArgumentException("Can not compute an angle with less than 3 points");
|
||||||
|
}
|
||||||
|
|
||||||
|
Angle3d[] angles = new Angle3d[coords.size()];
|
||||||
|
|
||||||
|
for (int i = 0; i < coords.size()-2; i++) {
|
||||||
|
angles[i] = new Angle3d(coords.get(i), coords.get(i+1), coords.get(i+2));
|
||||||
|
}
|
||||||
|
angles[coords.size()-2] = new Angle3d(coords.get(coords.size()-2), coords.get(coords.size()-1), coords.get(0));
|
||||||
|
angles[coords.size()-1] = new Angle3d(coords.get(coords.size()-1), coords.get(0), coords.get(1));
|
||||||
|
|
||||||
|
|
||||||
|
double cumulated = 0;
|
||||||
|
for(Angle3d angle: angles) {
|
||||||
|
cumulated+=angle.angleD();
|
||||||
|
}
|
||||||
|
return cumulated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double angleSumFromPoints(List<Point> coords) {
|
||||||
|
if(coords.size()<3) {
|
||||||
|
throw new IllegalArgumentException("Can not compute an angle with less than 3 points");
|
||||||
|
}
|
||||||
|
|
||||||
|
Angle3d[] angles = new Angle3d[coords.size()];
|
||||||
|
|
||||||
|
for (int i = 0; i < coords.size()-2; i++) {
|
||||||
|
angles[i] = new Angle3d(coords.get(i).xyz, coords.get(i+1).xyz, coords.get(i+2).xyz);
|
||||||
|
}
|
||||||
|
angles[coords.size()-2] = new Angle3d(coords.get(coords.size()-2).xyz, coords.get(coords.size()-1).xyz, coords.get(0).xyz);
|
||||||
|
angles[coords.size()-1] = new Angle3d(coords.get(coords.size()-1).xyz, coords.get(0).xyz, coords.get(1).xyz);
|
||||||
|
|
||||||
|
|
||||||
|
double cumulated = 0;
|
||||||
|
for(Angle3d angle: angles) {
|
||||||
|
cumulated+=angle.angleD();
|
||||||
|
}
|
||||||
|
return cumulated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the expected sum of all angles of a polygon given its number of points.
|
||||||
|
*
|
||||||
|
* The polygon is supposed to not have any edge crossing another edge.
|
||||||
|
*
|
||||||
|
* @param n
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double angleSumOfNonIntersectingPolygon(int n) {
|
||||||
|
if(n<3)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return (n-2)*180;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double angleSumOfNonIntersectingPolygonRad(int n) {
|
||||||
|
if(n<3)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return (n-2)*Math.PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean angleSumFromPointsOfNonIntersectingPolygon(List<Point> coords) {
|
||||||
|
double diff= Math.abs(angleSumFromPoints(coords)-angleSumOfNonIntersectingPolygonRad(coords.size()));
|
||||||
|
return diff<0.0001;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,10 @@ public class Coord3d implements Serializable {
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -1636927109633279805L;
|
private static final long serialVersionUID = -1636927109633279805L;
|
||||||
|
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
public float z;
|
||||||
|
|
||||||
public static List<Coord3d> list(int size) {
|
public static List<Coord3d> list(int size) {
|
||||||
return new ArrayList<Coord3d>(size);
|
return new ArrayList<Coord3d>(size);
|
||||||
}
|
}
|
||||||
|
@ -254,6 +258,13 @@ public class Coord3d implements Serializable {
|
||||||
z /= c2.z;
|
z /= c2.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void divSelf(float value) {
|
||||||
|
x /= value;
|
||||||
|
y /= value;
|
||||||
|
z /= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divise all components of the current Coord by the same value and return the result in a new
|
* Divise all components of the current Coord by the same value and return the result in a new
|
||||||
* Coord3d.
|
* Coord3d.
|
||||||
|
@ -376,6 +387,7 @@ public class Coord3d implements Serializable {
|
||||||
return Math.sqrt(distanceSq(c));
|
return Math.sqrt(distanceSq(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Compute the square distance between two coordinates. */
|
||||||
public double distanceSq(Coord3d c) {
|
public double distanceSq(Coord3d c) {
|
||||||
return Math.pow(x - c.x, 2) + Math.pow(y - c.y, 2) + Math.pow(z - c.z, 2);
|
return Math.pow(x - c.x, 2) + Math.pow(y - c.y, 2) + Math.pow(z - c.z, 2);
|
||||||
}
|
}
|
||||||
|
@ -605,9 +617,4 @@ public class Coord3d implements Serializable {
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************/
|
|
||||||
|
|
||||||
public float x;
|
|
||||||
public float y;
|
|
||||||
public float z;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.jzy3d.maths;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate all possible permutations of the input list
|
||||||
|
*
|
||||||
|
* May study https://www.quickperm.org/ as an faster alternative.
|
||||||
|
*
|
||||||
|
* @author martin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Permutations {
|
||||||
|
public static <E> List<List<E>> of(List<E> original) {
|
||||||
|
if (original.isEmpty()) {
|
||||||
|
List<List<E>> result = new ArrayList<>();
|
||||||
|
result.add(new ArrayList<>());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
E firstElement = original.remove(0);
|
||||||
|
List<List<E>> returnValue = new ArrayList<>();
|
||||||
|
List<List<E>> permutations = of(original);
|
||||||
|
for (List<E> smallerPermutated : permutations) {
|
||||||
|
for (int index = 0; index <= smallerPermutated.size(); index++) {
|
||||||
|
List<E> temp = new ArrayList<>(smallerPermutated);
|
||||||
|
temp.add(index, firstElement);
|
||||||
|
returnValue.add(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,11 @@ public abstract class Geometry extends Wireframeable implements ISingleColorable
|
||||||
add(points);
|
add(points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Geometry(List<Point> points) {
|
||||||
|
this();
|
||||||
|
add(points);
|
||||||
|
}
|
||||||
|
|
||||||
public Geometry(Color wireframeColor, Point... points) {
|
public Geometry(Color wireframeColor, Point... points) {
|
||||||
this(points);
|
this(points);
|
||||||
setWireframeColor(wireframeColor);
|
setWireframeColor(wireframeColor);
|
||||||
|
@ -188,6 +193,13 @@ public abstract class Geometry extends Wireframeable implements ISingleColorable
|
||||||
updateBounds();
|
updateBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void add(List<Point> points) {
|
||||||
|
for(Point p: points) {
|
||||||
|
add(p, false);
|
||||||
|
}
|
||||||
|
updateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyGeometryTransform(Transform transform) {
|
public void applyGeometryTransform(Transform transform) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.jzy3d.plot3d.primitives;
|
package org.jzy3d.plot3d.primitives;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import org.jzy3d.colors.Color;
|
import org.jzy3d.colors.Color;
|
||||||
import org.jzy3d.painters.IPainter;
|
import org.jzy3d.painters.IPainter;
|
||||||
|
|
||||||
|
@ -22,6 +23,10 @@ public class Polygon extends Geometry {
|
||||||
super(points);
|
super(points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Polygon(List<Point> points) {
|
||||||
|
super(points);
|
||||||
|
}
|
||||||
|
|
||||||
public Polygon(Color wire, Point... points) {
|
public Polygon(Color wire, Point... points) {
|
||||||
super(wire, points);
|
super(wire, points);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,9 @@ import org.jzy3d.painters.IPainter;
|
||||||
import org.jzy3d.plot3d.transform.Transform;
|
import org.jzy3d.plot3d.transform.Transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Experimental 3d object.
|
* A collection of coordinates rendered as dots.
|
||||||
|
*
|
||||||
|
* Warning : dots having a width of 1 may not be visible in case HiDPI is ON.
|
||||||
*
|
*
|
||||||
* @author Martin Pernollet
|
* @author Martin Pernollet
|
||||||
*
|
*
|
||||||
|
@ -28,17 +30,33 @@ public class Scatter extends Drawable implements ISingleColorable {
|
||||||
this(coordinates, Color.BLACK);
|
this(coordinates, Color.BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Scatter(List<Coord3d> coordinates) {
|
||||||
|
this(coordinates, Color.BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
public Scatter(Coord3d[] coordinates, Color rgb) {
|
public Scatter(Coord3d[] coordinates, Color rgb) {
|
||||||
this(coordinates, rgb, 1.0f);
|
this(coordinates, rgb, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Scatter(List<Coord3d> coordinates, Color rgb) {
|
||||||
|
this(coordinates, rgb, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
public Scatter(Coord3d[] coordinates, Color rgb, float width) {
|
public Scatter(Coord3d[] coordinates, Color rgb, float width) {
|
||||||
bbox = new BoundingBox3d();
|
this();
|
||||||
setData(coordinates);
|
setData(coordinates);
|
||||||
setWidth(width);
|
setWidth(width);
|
||||||
setColor(rgb);
|
setColor(rgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Scatter(List<Coord3d> coordinates, Color rgb, float width) {
|
||||||
|
this();
|
||||||
|
setData(coordinates);
|
||||||
|
setWidth(width);
|
||||||
|
setColor(rgb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Scatter(Coord3ds coords) {
|
public Scatter(Coord3ds coords) {
|
||||||
this(coords.coordsArray(), coords.colorsArray());
|
this(coords.coordsArray(), coords.colorsArray());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,26 @@
|
||||||
package org.jzy3d.plot3d.primitives.axis.layout.renderers;
|
package org.jzy3d.plot3d.primitives.axis.layout.renderers;
|
||||||
|
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class IntegerTickRenderer implements ITickRenderer {
|
public class IntegerTickRenderer implements ITickRenderer {
|
||||||
public IntegerTickRenderer() {}
|
boolean separator = false;
|
||||||
|
|
||||||
|
public IntegerTickRenderer() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegerTickRenderer(boolean separator) {
|
||||||
|
this.separator = separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String format(double value) {
|
public String format(double value) {
|
||||||
return "" + (int) value;
|
if(separator)
|
||||||
|
return NumberFormat.getNumberInstance(Locale.US).format((int) value);
|
||||||
|
else
|
||||||
|
return ""+(int) value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
package org.jzy3d.maths;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.jzy3d.colors.Color;
|
||||||
|
import org.jzy3d.plot3d.primitives.Point;
|
||||||
|
import org.jzy3d.plot3d.primitives.Polygon;
|
||||||
|
|
||||||
|
public class TestAngle3d {
|
||||||
|
@Test
|
||||||
|
public void testAngle90and45_Vertical() {
|
||||||
|
|
||||||
|
// Given on horizontal square
|
||||||
|
Polygon p1 = new Polygon();
|
||||||
|
p1.add(new Point(new Coord3d(0, 0, 0), Color.BLUE)); // P1 left bottom
|
||||||
|
p1.add(new Point(new Coord3d(1, 0, 0), Color.BLUE)); // neighbor edge will be dropped
|
||||||
|
p1.add(new Point(new Coord3d(1, 1, 0), Color.BLUE)); // neighbor edge will be dropped
|
||||||
|
p1.add(new Point(new Coord3d(0, 1, 0), Color.BLUE)); // P1 left top
|
||||||
|
|
||||||
|
|
||||||
|
// When computing angle
|
||||||
|
|
||||||
|
Angle3d a1 = new Angle3d(p1.get(0).xyz, p1.get(1).xyz, p1.get(2).xyz);
|
||||||
|
|
||||||
|
|
||||||
|
Angle3d a2 = new Angle3d(p1.get(0).xyz, p1.get(1).xyz, p1.get(3).xyz);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
Assert.assertEquals(Angle3d.DEGREE_90, a1.angle(), 0.0001);
|
||||||
|
Assert.assertEquals(Angle3d.DEGREE_45, a2.angle(), 0.0001);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAngle90and45_Horizontal() {
|
||||||
|
|
||||||
|
// Given on horizontal square
|
||||||
|
Polygon p1 = new Polygon();
|
||||||
|
p1.add(new Point(new Coord3d(0, 0, 0), Color.BLUE)); // P1 left bottom
|
||||||
|
p1.add(new Point(new Coord3d(0, 0, 1), Color.BLUE)); // neighbor edge will be dropped
|
||||||
|
p1.add(new Point(new Coord3d(0, 1, 1), Color.BLUE)); // neighbor edge will be dropped
|
||||||
|
p1.add(new Point(new Coord3d(0, 1, 0), Color.BLUE)); // P1 left top
|
||||||
|
|
||||||
|
|
||||||
|
// When computing angle
|
||||||
|
|
||||||
|
Angle3d a1 = new Angle3d(p1.get(0).xyz, p1.get(1).xyz, p1.get(2).xyz);
|
||||||
|
|
||||||
|
|
||||||
|
Angle3d a2 = new Angle3d(p1.get(0).xyz, p1.get(1).xyz, p1.get(3).xyz);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
Assert.assertEquals(Angle3d.DEGREE_90, a1.angle(), 0.0001);
|
||||||
|
Assert.assertEquals(Angle3d.DEGREE_45, a2.angle(), 0.0001);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSumingAnglesOfPolygon_TriangleIs180_SquareIs360() {
|
||||||
|
// square
|
||||||
|
Coord3d c1 = new Coord3d(0,0,0); // bottom left
|
||||||
|
Coord3d c2 = new Coord3d(1,0,0); // bottom right
|
||||||
|
Coord3d c3 = new Coord3d(1,1,0); // top right
|
||||||
|
Coord3d c4 = new Coord3d(0,1,0);
|
||||||
|
|
||||||
|
Assert.assertEquals(2*Math.PI, Angle3d.angleSum(Coord3d.list(c1,c2,c3,c4)), 0.0001);
|
||||||
|
Assert.assertEquals(Math.PI, Angle3d.angleSum(Coord3d.list(c1,c2,c3)), 0.0001);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test(expected=IllegalArgumentException.class)
|
||||||
|
public void sumOfIncompleteAngles() {
|
||||||
|
Angle3d.angleSum(Coord3d.list(Coord3d.IDENTITY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=IllegalArgumentException.class)
|
||||||
|
public void sumOfIncompleteAngles2() {
|
||||||
|
Angle3d.angleSum(Coord3d.list(Coord3d.IDENTITY, Coord3d.IDENTITY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sumOfAnglesExpect() {
|
||||||
|
Assert.assertEquals(180, Angle3d.angleSumOfNonIntersectingPolygon(3), 0.0001);
|
||||||
|
Assert.assertEquals(360, Angle3d.angleSumOfNonIntersectingPolygon(4), 0.0001);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@Test
|
||||||
|
public void testAngle90and45_nonPlanar() {
|
||||||
|
|
||||||
|
// Given
|
||||||
|
Polygon p1 = new Polygon();
|
||||||
|
p1.add(new Point(new Coord3d(0, 0, 0), Color.BLUE)); // P1 left bottom
|
||||||
|
p1.add(new Point(new Coord3d(1, 0, 1), Color.BLUE)); // neighbor edge will be dropped
|
||||||
|
p1.add(new Point(new Coord3d(1, 1, 0), Color.BLUE)); // neighbor edge will be dropped
|
||||||
|
p1.add(new Point(new Coord3d(0, 1, 0), Color.BLUE)); // P1 left top
|
||||||
|
|
||||||
|
|
||||||
|
// When computing angle
|
||||||
|
|
||||||
|
Angle3d a1 = new Angle3d(p1.get(0).xyz, p1.get(1).xyz, p1.get(2).xyz);
|
||||||
|
|
||||||
|
|
||||||
|
Angle3d a2 = new Angle3d(p1.get(0).xyz, p1.get(1).xyz, p1.get(3).xyz);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
Assert.assertEquals(Angle3d.DEGREE_90, a1.angle(), 0.0001);
|
||||||
|
Assert.assertEquals(Angle3d.DEGREE_45, a2.angle(), 0.0001);
|
||||||
|
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -91,4 +91,6 @@ public class TestCoord3d {
|
||||||
Assert.assertFalse(new Coord3d(Float.POSITIVE_INFINITY, 2, 3)
|
Assert.assertFalse(new Coord3d(Float.POSITIVE_INFINITY, 2, 3)
|
||||||
.equals(new Coord3d(Float.NEGATIVE_INFINITY, 2, 3)));
|
.equals(new Coord3d(Float.NEGATIVE_INFINITY, 2, 3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -46,6 +46,12 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jzy3d-io-xls</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package org.jzy3d.performance.polygons;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.jzy3d.chart.Chart;
|
||||||
|
import org.jzy3d.chart.factories.AWTChartFactory;
|
||||||
|
import org.jzy3d.chart.factories.ChartFactory;
|
||||||
|
import org.jzy3d.colors.Color;
|
||||||
|
import org.jzy3d.io.xls.ExcelBuilder;
|
||||||
|
import org.jzy3d.maths.BoundingBox3d;
|
||||||
|
import org.jzy3d.maths.Coord3d;
|
||||||
|
import org.jzy3d.painters.Font;
|
||||||
|
import org.jzy3d.plot3d.primitives.LineStrip;
|
||||||
|
import org.jzy3d.plot3d.primitives.Scatter;
|
||||||
|
import org.jzy3d.plot3d.primitives.axis.layout.LabelOrientation;
|
||||||
|
import org.jzy3d.plot3d.primitives.axis.layout.renderers.IntegerTickRenderer;
|
||||||
|
import org.jzy3d.plot3d.rendering.canvas.Quality;
|
||||||
|
|
||||||
|
public class BenchmarkPlot implements BenchmarkXLS{
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
|
// -------------------------------
|
||||||
|
// Chart configuration for plotting
|
||||||
|
ChartFactory f = new AWTChartFactory();
|
||||||
|
//ChartFactory f = new EmulGLChartFactory();
|
||||||
|
Quality q = Quality.Advanced();
|
||||||
|
//q.setHiDPI(HiDPI.OFF);
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------
|
||||||
|
// Collect benchmark data
|
||||||
|
|
||||||
|
int stepMin = 2; // min number of steps for surface
|
||||||
|
int stepMax = 100; // max number of steps for surface
|
||||||
|
String info = "emulgl-hidpi"; // HiDPI setting during benchmark
|
||||||
|
|
||||||
|
|
||||||
|
String file = BenchmarkUtils.getExcelFilename(outputFolder, stepMin, stepMax, info);
|
||||||
|
ExcelBuilder xls = new ExcelBuilder(file);
|
||||||
|
xls.setCurrentSheet(SHEET_BENCHMARK);
|
||||||
|
|
||||||
|
int line = 0;
|
||||||
|
|
||||||
|
|
||||||
|
List<Coord3d> data = new ArrayList<>();
|
||||||
|
|
||||||
|
Cell cellTime = xls.getCell(line, TIME);
|
||||||
|
Cell cellPoly = xls.getCell(line, POLYGONS);
|
||||||
|
|
||||||
|
double maxX = 0;
|
||||||
|
|
||||||
|
while(cellTime!=null && cellPoly!=null) {
|
||||||
|
double x = cellPoly.getNumericCellValue();
|
||||||
|
double y = cellTime.getNumericCellValue();
|
||||||
|
|
||||||
|
if(x>maxX)
|
||||||
|
maxX = x;
|
||||||
|
|
||||||
|
data.add(new Coord3d(x, y, 0));
|
||||||
|
|
||||||
|
cellTime = xls.getCell(line, TIME);
|
||||||
|
cellPoly = xls.getCell(line, POLYGONS);
|
||||||
|
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("loaded " + line + " XLS lines");
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------
|
||||||
|
// Plot benchmark data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Chart c = f.newChart(q);
|
||||||
|
|
||||||
|
c.view2d();
|
||||||
|
c.add(new Scatter(data, Color.BLUE, 2));
|
||||||
|
c.add(line(40, maxX, Color.GREEN, 2));
|
||||||
|
c.add(line(60, maxX, Color.ORANGE, 2));
|
||||||
|
c.add(line(80, maxX, Color.RED, 2));
|
||||||
|
c.getAxisLayout().setXAxisLabel("Number of polygons (polygons all together cover the same surface)");
|
||||||
|
c.getAxisLayout().setYAxisLabel("Rendering time (ms)");
|
||||||
|
c.getAxisLayout().setYAxisLabelOrientation(LabelOrientation.PARALLEL_TO_AXIS);
|
||||||
|
c.getAxisLayout().setFont(Font.Helvetica_18);
|
||||||
|
c.getAxisLayout().setXTickRenderer(new IntegerTickRenderer(true));
|
||||||
|
|
||||||
|
c.getView().setBoundManual(new BoundingBox3d(0, (float)maxX, 0, 400, -10, 10));
|
||||||
|
|
||||||
|
c.open(file, 1024, 768);
|
||||||
|
|
||||||
|
|
||||||
|
//DebugGLChart3d debugChart = new DebugGLChart3d(c, new AWTChartFactory());
|
||||||
|
//debugChart.open(new Rectangle(0, 0, 300, 300));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LineStrip line(int ms, double maxX, Color lineColor, int width) {
|
||||||
|
LineStrip line = new LineStrip(lineColor, new Coord3d(0, ms, 0), new Coord3d(maxX, ms, 0));
|
||||||
|
line.setWireframeWidth(width);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,188 @@
|
||||||
|
package org.jzy3d.performance.polygons;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.RuntimeMXBean;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.jzy3d.chart.Chart;
|
||||||
|
import org.jzy3d.chart.EmulGLSkin;
|
||||||
|
import org.jzy3d.chart.factories.AWTChartFactory;
|
||||||
|
import org.jzy3d.chart.factories.ChartFactory;
|
||||||
|
import org.jzy3d.chart.factories.EmulGLChartFactory;
|
||||||
|
import org.jzy3d.colors.Color;
|
||||||
|
import org.jzy3d.colors.ColorMapper;
|
||||||
|
import org.jzy3d.colors.colormaps.ColorMapRainbow;
|
||||||
|
import org.jzy3d.io.xls.ExcelBuilder;
|
||||||
|
import org.jzy3d.io.xls.ExcelBuilder.Type;
|
||||||
|
import org.jzy3d.maths.Range;
|
||||||
|
import org.jzy3d.maths.Statistics;
|
||||||
|
import org.jzy3d.maths.TicToc;
|
||||||
|
import org.jzy3d.plot3d.builder.Mapper;
|
||||||
|
import org.jzy3d.plot3d.builder.SurfaceBuilder;
|
||||||
|
import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid;
|
||||||
|
import org.jzy3d.plot3d.primitives.Shape;
|
||||||
|
import org.jzy3d.plot3d.rendering.canvas.Quality;
|
||||||
|
import org.jzy3d.plot3d.rendering.view.HiDPI;
|
||||||
|
|
||||||
|
public class BenchmarkRun implements BenchmarkXLS {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException, InterruptedException {
|
||||||
|
int width = 1024;
|
||||||
|
int height = 768;
|
||||||
|
HiDPI hidpi = HiDPI.ON;
|
||||||
|
boolean alphaEnabled = false;
|
||||||
|
String info = "native"; // for building file name
|
||||||
|
|
||||||
|
boolean offscreen = false;
|
||||||
|
int stepMax = 250; // max number of steps for surface
|
||||||
|
int stepMin = 2; // min number of steps for surface
|
||||||
|
int shoots = 30; // number of trials
|
||||||
|
|
||||||
|
boolean saveImages = false;
|
||||||
|
|
||||||
|
|
||||||
|
ExcelBuilder xls = new ExcelBuilder(Type.XLSX, SHEET_CONFIG);
|
||||||
|
|
||||||
|
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
||||||
|
|
||||||
|
Map<String, String> systemProperties = runtimeBean.getSystemProperties();
|
||||||
|
Set<String> keys = systemProperties.keySet();
|
||||||
|
|
||||||
|
int line = 0;
|
||||||
|
for (String key : keys) {
|
||||||
|
String value = systemProperties.get(key);
|
||||||
|
|
||||||
|
xls.setCell(line, 0, key);
|
||||||
|
xls.setCell(line, 1, value);
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// Configure base quality for standard case
|
||||||
|
|
||||||
|
// ChartFactory factory = new EmulGLChartFactory();
|
||||||
|
ChartFactory factory = new AWTChartFactory();
|
||||||
|
|
||||||
|
if (offscreen)
|
||||||
|
factory.getPainterFactory().setOffscreen(width, height);
|
||||||
|
|
||||||
|
Quality q = Quality.Advanced();
|
||||||
|
q.setAnimated(factory instanceof AWTChartFactory); // RESOLVE ME : CHART DOES NOT SHOW A NON
|
||||||
|
// ANIMATED AWT
|
||||||
|
q.setAlphaActivated(alphaEnabled);
|
||||||
|
q.setHiDPI(hidpi);
|
||||||
|
|
||||||
|
Chart chart = factory.newChart(q);
|
||||||
|
if (!offscreen)
|
||||||
|
chart.open(width, height);
|
||||||
|
|
||||||
|
// EmulGLSkin skin = EmulGLSkin.on(chart);
|
||||||
|
// chart.addMouseCameraController();
|
||||||
|
|
||||||
|
|
||||||
|
Shape surface = null;
|
||||||
|
|
||||||
|
xls.setCurrentSheet(xls.newSheet(SHEET_BENCHMARK));
|
||||||
|
|
||||||
|
|
||||||
|
line = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = stepMax; i >= stepMin; i--) {
|
||||||
|
|
||||||
|
|
||||||
|
if (surface != null) {
|
||||||
|
chart.remove(surface);
|
||||||
|
chart.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
surface = surface(i);
|
||||||
|
chart.add(surface);
|
||||||
|
|
||||||
|
int polygonNumber = surface.size();
|
||||||
|
|
||||||
|
|
||||||
|
int minPoly = Integer.MAX_VALUE;
|
||||||
|
int maxPoly = 0;
|
||||||
|
|
||||||
|
// Measure perf
|
||||||
|
double[] renderingTime = new double[shoots];
|
||||||
|
|
||||||
|
TicToc t = new TicToc();
|
||||||
|
|
||||||
|
for (int s = 0; s < shoots; s++) {
|
||||||
|
|
||||||
|
t.tic();
|
||||||
|
chart.render();
|
||||||
|
t.toc();
|
||||||
|
|
||||||
|
renderingTime[s] = t.elapsedMilisecond();
|
||||||
|
|
||||||
|
if (renderingTime[s] < 40) {
|
||||||
|
Thread.sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
xls.setCell(line, TIME, renderingTime[s]);
|
||||||
|
xls.setCell(line, POLYGONS, polygonNumber);
|
||||||
|
xls.setCell(line, WIDTH, width);
|
||||||
|
xls.setCell(line, HEIGHT, height);
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (polygonNumber > maxPoly) {
|
||||||
|
maxPoly = polygonNumber;
|
||||||
|
}
|
||||||
|
if (polygonNumber < minPoly) {
|
||||||
|
minPoly = polygonNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// System.out.println("Median perf for " + n + " polygons : "
|
||||||
|
// + Statistics.median(perf, false) + " after " + shoots + " shoots");
|
||||||
|
// Array.print(perf);
|
||||||
|
|
||||||
|
System.out.println(polygonNumber + ", " + (width * height) + ", "
|
||||||
|
+ Statistics.median(renderingTime, false) + ", " + shoots);
|
||||||
|
|
||||||
|
if (saveImages)
|
||||||
|
chart.screenshot(new File("target/bench-" + polygonNumber + ".png"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish
|
||||||
|
String file = BenchmarkUtils.getExcelFilename(outputFolder, stepMin, stepMax, info);
|
||||||
|
xls.save(file);
|
||||||
|
|
||||||
|
System.out.println("Wrote " + file + " with " + line + " lines");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static Shape surface(int steps) {
|
||||||
|
SurfaceBuilder builder = new SurfaceBuilder();
|
||||||
|
|
||||||
|
Mapper mapper = new Mapper() {
|
||||||
|
@Override
|
||||||
|
public double f(double x, double y) {
|
||||||
|
return 0;// x * Math.sin(x * y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Range range = new Range(-3, 3);
|
||||||
|
|
||||||
|
Shape surface = builder.orthonormal(new OrthonormalGrid(range, steps), mapper);
|
||||||
|
|
||||||
|
ColorMapper colorMapper = new ColorMapper(new ColorMapRainbow(), surface);
|
||||||
|
surface.setColorMapper(colorMapper);
|
||||||
|
surface.setFaceDisplayed(true);
|
||||||
|
surface.setWireframeDisplayed(false);
|
||||||
|
surface.setWireframeColor(Color.BLACK);
|
||||||
|
surface.setWireframeWidth(1);
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.jzy3d.performance.polygons;
|
||||||
|
|
||||||
|
public class BenchmarkUtils {
|
||||||
|
public static String getExcelFilename(String outputFolder, int stepMin, int stepMax,
|
||||||
|
String info) {
|
||||||
|
return outputFolder + "/bench-" + stepMin + "-" + stepMax + "-" + info + ".xlsx";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.jzy3d.performance.polygons;
|
||||||
|
|
||||||
|
public interface BenchmarkXLS {
|
||||||
|
int TIME = 0;
|
||||||
|
int POLYGONS = 1;
|
||||||
|
int WIDTH = 2;
|
||||||
|
int HEIGHT = 3;
|
||||||
|
|
||||||
|
String SHEET_CONFIG = "config";
|
||||||
|
String SHEET_BENCHMARK = "benchmark";
|
||||||
|
|
||||||
|
String outputFolder = "./data";
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue