From 32870092e0390353e5968f567b0202f98bc3fd49 Mon Sep 17 00:00:00 2001 From: Richard Tingle <6330028+richardTingle@users.noreply.github.com> Date: Sat, 18 Dec 2021 15:22:19 +0000 Subject: [PATCH 1/8] #6 Add a builder for the curve class that allows it to be specified as a series of anchor and control points --- .../com/epaga/particles/valuetypes/Curve.java | 35 +++++++++++++++ .../curvebuilder/CurveBuilderAtAnchor.java | 45 +++++++++++++++++++ .../CurveBuilderAtControlPoint1.java | 25 +++++++++++ .../CurveBuilderAtControlPoint2.java | 26 +++++++++++ .../curvebuilder/CurveBuilderStart.java | 19 ++++++++ 5 files changed, 150 insertions(+) create mode 100644 src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java create mode 100644 src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java create mode 100644 src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java create mode 100644 src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java diff --git a/src/main/java/com/epaga/particles/valuetypes/Curve.java b/src/main/java/com/epaga/particles/valuetypes/Curve.java index 831c6a6..94045ac 100644 --- a/src/main/java/com/epaga/particles/valuetypes/Curve.java +++ b/src/main/java/com/epaga/particles/valuetypes/Curve.java @@ -31,6 +31,8 @@ */ package com.epaga.particles.valuetypes; +import com.epaga.particles.valuetypes.curvebuilder.CurveBuilderAtAnchor; +import com.epaga.particles.valuetypes.curvebuilder.CurveBuilderStart; import com.jme3.export.*; import com.jme3.math.Vector2f; @@ -158,4 +160,37 @@ public boolean equals(Object o) { return true; } + + + /** + * Produces a builder that can be used to fluently build a curve. A Curve will always be continuous (And should + * move in a positive X direction) but the gradient may change sharply. + * + * It is a series of anchor points connected either by straight line sections or cubic besier curves (defined by + * 2 control points). + * + * In normal usage the first anchor point should be at x = 0, all further points should advance in the X axis and + * the final anchor point should have x at 1. This is because usually X is the fractional life of the particle + * + * Example usage: + * + *
{@code
+ * Curve curve = Curve.builder()
+ * .anchorPoint(new Vector2f(0,0))
+ * .anchorPoint(new Vector2f(0.5f,0.5f))
+ * .controlPoint1(new Vector2f(0.6f,0.5f))
+ * .controlPoint2(new Vector2f(0.8f,2f))
+ * .anchorPoint(new Vector2f(1,2f))
+ * .build();
+ * }
+ *
+ * This example produces a straight line from (0,0) -> (0.5,0.5), then a cubic Besier curves between (0.5,0.5) -> (1,2) with control points (0.6,0.5) and (0.8,2)
+ *
+ * Note that a builder should not be reused.
+ *
+ * @return a CurveBuilderStart
+ */
+ public static CurveBuilderStart builder(){
+ return new CurveBuilderStart();
+ }
}
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
new file mode 100644
index 0000000..80aba70
--- /dev/null
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
@@ -0,0 +1,45 @@
+package com.epaga.particles.valuetypes.curvebuilder;
+
+import com.epaga.particles.valuetypes.Curve;
+import com.jme3.math.Vector2f;
+
+public class CurveBuilderAtAnchor{
+
+ Curve curveBeingBuilt;
+ Vector2f controlPointIn;
+ Vector2f currentAnchor;
+
+ public CurveBuilderAtAnchor(Curve curveBeingBuilt, Vector2f controlPointIn, Vector2f currentAnchor){
+ this.curveBeingBuilt = curveBeingBuilt;
+ this.controlPointIn = controlPointIn;
+ this.currentAnchor = currentAnchor;
+ }
+
+ /**
+ * Adds a point that the curve will attempt to move towards but may not actually touch.
+ *
+ * The 2 control points are used to define a cubic Bézier curve between 2 anchors
+ * @param nextControlPoint the control point
+ * @return a CurveBuilderAtControlPoint1 a part of the curve builder system
+ */
+ public CurveBuilderAtControlPoint1 controlPoint1( Vector2f nextControlPoint ){
+ return new CurveBuilderAtControlPoint1(curveBeingBuilt, controlPointIn, currentAnchor, nextControlPoint);
+ }
+
+ /**
+ * Produces a straight line between 2 anchor points
+ * @param nextAnchor the next anchor point
+ * @return a CurveBuilderAtAnchor a part of the curve builder system
+ */
+ public CurveBuilderAtAnchor anchorPoint(Vector2f nextAnchor ){
+ //simulate a straight line using a Bézier curve
+ Vector2f midOne = currentAnchor.mult(2f/3).add(nextAnchor.mult(1f/3));
+ Vector2f midTwo = currentAnchor.mult(1f/3).add(nextAnchor.mult(2f/3));
+ return controlPoint1(midOne).controlPoint2(midTwo).nextAnchor(nextAnchor);
+ }
+
+ public Curve end(){
+ curveBeingBuilt.addControlPoint(controlPointIn, currentAnchor, null);
+ return curveBeingBuilt;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
new file mode 100644
index 0000000..353c470
--- /dev/null
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
@@ -0,0 +1,25 @@
+package com.epaga.particles.valuetypes.curvebuilder;
+
+import com.epaga.particles.valuetypes.Curve;
+import com.jme3.math.Vector2f;
+
+public class CurveBuilderAtControlPoint1{
+
+ Curve curveBeingBuilt;
+
+ public CurveBuilderAtControlPoint1(Curve curveBeingBuilt, Vector2f controlPointIn, Vector2f currentAnchor, Vector2f controlPointOut){
+ this.curveBeingBuilt = curveBeingBuilt;
+ this.curveBeingBuilt.addControlPoint(controlPointIn, currentAnchor, controlPointOut);
+ }
+
+ /**
+ * Adds a point that the curve will attempt to move towards but may not actually touch.
+ *
+ * The 2 control points are used to define a cubic Bézier curve between 2 anchors
+ * @param nextControlPoint the control point
+ * @return a CurveBuilderAtControlPoint1 a part of the curve builder system
+ */
+ public CurveBuilderAtControlPoint2 controlPoint2( Vector2f nextControlPoint ){
+ return new CurveBuilderAtControlPoint2(curveBeingBuilt, nextControlPoint);
+ }
+}
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
new file mode 100644
index 0000000..4e1f926
--- /dev/null
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
@@ -0,0 +1,26 @@
+package com.epaga.particles.valuetypes.curvebuilder;
+
+import com.epaga.particles.valuetypes.Curve;
+import com.jme3.math.Vector2f;
+
+public class CurveBuilderAtControlPoint2{
+
+ Curve curveBeingBuilt;
+ Vector2f inControlPoint;
+
+ public CurveBuilderAtControlPoint2(Curve curveBeingBuilt, Vector2f inControlPoint){
+ this.curveBeingBuilt = curveBeingBuilt;
+ this.inControlPoint = inControlPoint;
+ }
+
+ /**
+ * Adds a point that the curve go through.
+ *
+ * Anchors are the starts and ends of cubic Bézier curves
+ * @param nextAnchor the anchor point
+ * @return a CurveBuilderAtAnchor a part of the curve builder system
+ */
+ public CurveBuilderAtAnchor anchorPoint(Vector2f nextAnchor ){
+ return new CurveBuilderAtAnchor(curveBeingBuilt, inControlPoint, nextAnchor);
+ }
+}
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java
new file mode 100644
index 0000000..eec04db
--- /dev/null
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java
@@ -0,0 +1,19 @@
+package com.epaga.particles.valuetypes.curvebuilder;
+
+import com.epaga.particles.valuetypes.Curve;
+import com.jme3.math.Vector2f;
+import com.jme3.math.Vector3f;
+
+public class CurveBuilderStart{
+
+ Curve curveBeingBuilt = new Curve();
+
+ /**
+ * Adds the first anchor point, where the line will start
+ * @return CurveBuilderAtAnchor a part of the curve builder system
+ */
+ public CurveBuilderAtAnchor anchorPoint(Vector2f start){
+ return new CurveBuilderAtAnchor(curveBeingBuilt, null, start);
+ }
+
+}
From 1b30a2485d2f02164ced36068d55e0c49916106d Mon Sep 17 00:00:00 2001
From: Richard Tingle <6330028+richardTingle@users.noreply.github.com>
Date: Sat, 18 Dec 2021 15:33:25 +0000
Subject: [PATCH 2/8] #6 Allow direct passing of floats and add to size
influencer javadoc
---
.../epaga/particles/influencers/SizeInfluencer.java | 7 +++++++
.../curvebuilder/CurveBuilderAtAnchor.java | 12 +++++++++++-
.../valuetypes/curvebuilder/CurveBuilderStart.java | 4 ++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/src/main/java/com/epaga/particles/influencers/SizeInfluencer.java b/src/main/java/com/epaga/particles/influencers/SizeInfluencer.java
index 4f71ee4..ebff8b5 100644
--- a/src/main/java/com/epaga/particles/influencers/SizeInfluencer.java
+++ b/src/main/java/com/epaga/particles/influencers/SizeInfluencer.java
@@ -44,6 +44,13 @@
* Size Module
* The size module controls the particle size over time
*
+ * To create a size inflencer that linearly changes the particle size from 0.3 to 0.1 over its lifetime create like:
+ * {@code
+ * ValueType sizeOverTime = new ValueType(Curve.builder().anchorPoint(0f, 0.03f).anchorPoint(1f, 0.01f).end());
+ * SizeInfluencer sizeInfluencer = new SizeInfluencer();
+ * sizeInfluencer.setSizeOverTime(sizeOverTime);
+ * }
+ *
* @author t0neg0d
* @author Jeddic
*/
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
index 80aba70..999ff35 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
@@ -26,6 +26,16 @@ public CurveBuilderAtControlPoint1 controlPoint1( Vector2f nextControlPoint ){
return new CurveBuilderAtControlPoint1(curveBeingBuilt, controlPointIn, currentAnchor, nextControlPoint);
}
+ /**
+ * Produces a straight line between 2 anchor points
+ * @param x the x of the next anchor point
+ * @param y the y of the next anchor point
+ * @return a CurveBuilderAtAnchor a part of the curve builder system
+ */
+ public CurveBuilderAtAnchor anchorPoint(float x, float y){
+ return anchorPoint(new Vector2f(x,y));
+ }
+
/**
* Produces a straight line between 2 anchor points
* @param nextAnchor the next anchor point
@@ -35,7 +45,7 @@ public CurveBuilderAtAnchor anchorPoint(Vector2f nextAnchor ){
//simulate a straight line using a Bézier curve
Vector2f midOne = currentAnchor.mult(2f/3).add(nextAnchor.mult(1f/3));
Vector2f midTwo = currentAnchor.mult(1f/3).add(nextAnchor.mult(2f/3));
- return controlPoint1(midOne).controlPoint2(midTwo).nextAnchor(nextAnchor);
+ return controlPoint1(midOne).controlPoint2(midTwo).anchorPoint(nextAnchor);
}
public Curve end(){
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java
index eec04db..8e45793 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java
@@ -8,6 +8,10 @@ public class CurveBuilderStart{
Curve curveBeingBuilt = new Curve();
+ public CurveBuilderAtAnchor anchorPoint(float x, float y){
+ return anchorPoint(new Vector2f(x,y));
+ }
+
/**
* Adds the first anchor point, where the line will start
* @return CurveBuilderAtAnchor a part of the curve builder system
From 751f43a7ded0d1801e33bed9068a9c5da733871e Mon Sep 17 00:00:00 2001
From: Richard Tingle <6330028+richardTingle@users.noreply.github.com>
Date: Sat, 18 Dec 2021 16:40:45 +0000
Subject: [PATCH 3/8] #6 Add unit tests for the curve builder (and so
implicitly the curve)
---
.../curvebuilder/CurveBuilderAtAnchor.java | 12 +++
.../CurveBuilderAtControlPoint1.java | 12 +++
.../CurveBuilderAtControlPoint2.java | 12 +++
.../epaga/particles/valuetypes/CurveTest.java | 74 +++++++++++++++++++
4 files changed, 110 insertions(+)
create mode 100644 src/test/java/com/epaga/particles/valuetypes/CurveTest.java
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
index 999ff35..f17d8dd 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
@@ -15,6 +15,18 @@ public CurveBuilderAtAnchor(Curve curveBeingBuilt, Vector2f controlPointIn, Vect
this.currentAnchor = currentAnchor;
}
+ /**
+ * Adds a point that the curve will attempt to move towards but may not actually touch.
+ *
+ * The 2 control points are used to define a cubic Bézier curve between 2 anchors
+ * @param x the next control point's x
+ * @param y the next control point's y
+ * @return a CurveBuilderAtControlPoint1 a part of the curve builder system
+ */
+ public CurveBuilderAtControlPoint1 controlPoint1( float x, float y ){
+ return controlPoint1(new Vector2f(x,y));
+ }
+
/**
* Adds a point that the curve will attempt to move towards but may not actually touch.
*
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
index 353c470..07c939f 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
@@ -16,6 +16,18 @@ public CurveBuilderAtControlPoint1(Curve curveBeingBuilt, Vector2f controlPointI
* Adds a point that the curve will attempt to move towards but may not actually touch.
*
* The 2 control points are used to define a cubic Bézier curve between 2 anchors
+ * @param x the control point's x
+ * @param y the control point's y
+ * @return a CurveBuilderAtControlPoint1 a part of the curve builder system
+ */
+ public CurveBuilderAtControlPoint2 controlPoint2( float x, float y ){
+ return controlPoint2(new Vector2f(x, y));
+ }
+
+ /**
+ * Adds a point that the curve will attempt to move towards (but may not actually touch).
+ *
+ * The 2 control points are used to define a cubic Bézier curve between 2 anchors
* @param nextControlPoint the control point
* @return a CurveBuilderAtControlPoint1 a part of the curve builder system
*/
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
index 4e1f926..c0e242e 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
@@ -13,6 +13,18 @@ public CurveBuilderAtControlPoint2(Curve curveBeingBuilt, Vector2f inControlPoin
this.inControlPoint = inControlPoint;
}
+ /**
+ * Adds a point that the curve go through.
+ *
+ * Anchors are the starts and ends of cubic Bézier curves
+ * @param x the anchor point's x
+ * @param y the anchor point's y
+ * @return a CurveBuilderAtAnchor a part of the curve builder system
+ */
+ public CurveBuilderAtAnchor anchorPoint(float x, float y){
+ return anchorPoint(new Vector2f(x, y));
+ }
+
/**
* Adds a point that the curve go through.
*
diff --git a/src/test/java/com/epaga/particles/valuetypes/CurveTest.java b/src/test/java/com/epaga/particles/valuetypes/CurveTest.java
new file mode 100644
index 0000000..10c1b75
--- /dev/null
+++ b/src/test/java/com/epaga/particles/valuetypes/CurveTest.java
@@ -0,0 +1,74 @@
+package com.epaga.particles.valuetypes;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class CurveTest{
+
+ @Test
+ public void builder_straightLine(){
+ Curve curve = Curve.builder()
+ .anchorPoint(0,0)
+ .anchorPoint(1,10)
+ .end();
+
+ assertEquals(0, curve.getValue(0f), 0.001);
+ assertEquals(4, curve.getValue(0.4f), 0.001);
+ assertEquals(10, curve.getValue(1f), 0.001);
+ }
+
+ /**
+ * Tests that 2 straight lines joined together functions correctly
+ */
+ @Test
+ public void builder_doubleStraightLine(){
+ Curve curve = Curve.builder()
+ .anchorPoint(0,0)
+ .anchorPoint(0.4f,10)
+ .anchorPoint(1f, 10)
+ .end();
+
+ assertEquals(0, curve.getValue(0f), 0.001);
+ assertEquals(5, curve.getValue(0.2f), 0.001);
+ assertEquals(10, curve.getValue(0.8f), 0.001);
+ }
+
+ /**
+ * Tests that a Bézier-like curve functions correctly
+ *
+ * (Its not actually a true Bézier curve becuse a Bézier curve can "go backwards" and follows a
+ * slightly different path
+ */
+ @Test
+ public void builder_curve(){
+
+ Curve curve = Curve.builder()
+ .anchorPoint(0,0)
+ .controlPoint1(0.2f, 1)
+ .controlPoint2(0.8f, 0)
+ .anchorPoint(1,1)
+ .end();
+
+ //expected values obtained using https://www.desmos.com/calculator/ebdtbxgbq0
+
+ assertEquals(0, curve.getValue(0f), 0.001);
+
+ //value obtained as 0.1 along using the following
+ // along line 1 = 0.9 * 0 + 0.1 * 1 = 0.1
+ // along line 2 = 0.9 * 1 + 0.1 * 0 = 0.9
+ // along line 3 = 0.9 * 0 + 0.1 * 1 = 0.1
+
+ //obtain 2 new lines between along line 1 -> along line 2 and along line 2 -> along line 3. Get 0.1 along each one
+ //along second order 1 = 0.9 * 0.1 + 0.1 * 0.9 = 0.18
+ //along second order 2 = 0.9 * 0.9 + 0.1 * 0.1 = 0.82
+
+ //final result is 0.1 along the line between the second order points
+ // 0.9 * 0.18 + 0.1 * 0.82
+
+ assertEquals(0.244, curve.getValue(0.1f), 0.001);
+
+ assertEquals(0.5, curve.getValue(0.5f), 0.001);
+ assertEquals(1, curve.getValue(1), 0.001);
+ }
+}
\ No newline at end of file
From e08906dd0501c81ce0ba48f6de8d2ba3296d7170 Mon Sep 17 00:00:00 2001
From: Richard Tingle <6330028+richardTingle@users.noreply.github.com>
Date: Sat, 18 Dec 2021 16:42:41 +0000
Subject: [PATCH 4/8] #6 Correct javadoc as these are not actual bezier curves
---
src/main/java/com/epaga/particles/valuetypes/Curve.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/main/java/com/epaga/particles/valuetypes/Curve.java b/src/main/java/com/epaga/particles/valuetypes/Curve.java
index 94045ac..0a7787c 100644
--- a/src/main/java/com/epaga/particles/valuetypes/Curve.java
+++ b/src/main/java/com/epaga/particles/valuetypes/Curve.java
@@ -166,8 +166,9 @@ public boolean equals(Object o) {
* Produces a builder that can be used to fluently build a curve. A Curve will always be continuous (And should
* move in a positive X direction) but the gradient may change sharply.
*
- * It is a series of anchor points connected either by straight line sections or cubic besier curves (defined by
- * 2 control points).
+ * It is a series of anchor points connected either by straight line sections or cubic Bézier-like curves (defined by
+ * 2 control points). They are bezier-like curves not Bézier curves because of the requirement that X (often
+ * representing time) can only be allowed to move forward
*
* In normal usage the first anchor point should be at x = 0, all further points should advance in the X axis and
* the final anchor point should have x at 1. This is because usually X is the fractional life of the particle
From 5f964880b8758d32dda2350a3048461171611e3e Mon Sep 17 00:00:00 2001
From: Richard Tingle <6330028+richardTingle@users.noreply.github.com>
Date: Sat, 18 Dec 2021 16:58:07 +0000
Subject: [PATCH 5/8] #6 Prevent illegal reuse of the curve builder (which
would cause very weird behaviour)
---
.../curvebuilder/CurveBuilderAtAnchor.java | 22 +++++++++++--------
.../CurveBuilderAtControlPoint1.java | 3 ++-
.../CurveBuilderAtControlPoint2.java | 3 ++-
.../curvebuilder/CurveBuilderPiece.java | 13 +++++++++++
.../curvebuilder/CurveBuilderStart.java | 3 ++-
.../epaga/particles/valuetypes/CurveTest.java | 19 ++++++++++++----
6 files changed, 47 insertions(+), 16 deletions(-)
create mode 100644 src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderPiece.java
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
index f17d8dd..6cb3144 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
@@ -3,11 +3,11 @@
import com.epaga.particles.valuetypes.Curve;
import com.jme3.math.Vector2f;
-public class CurveBuilderAtAnchor{
+public class CurveBuilderAtAnchor extends CurveBuilderPiece{
- Curve curveBeingBuilt;
- Vector2f controlPointIn;
- Vector2f currentAnchor;
+ private final Curve curveBeingBuilt;
+ private final Vector2f controlPointIn;
+ private final Vector2f currentAnchor;
public CurveBuilderAtAnchor(Curve curveBeingBuilt, Vector2f controlPointIn, Vector2f currentAnchor){
this.curveBeingBuilt = curveBeingBuilt;
@@ -16,9 +16,9 @@ public CurveBuilderAtAnchor(Curve curveBeingBuilt, Vector2f controlPointIn, Vect
}
/**
- * Adds a point that the curve will attempt to move towards but may not actually touch.
+ * Adds a point that the curve will attempt to move towards (but may not actually touch).
*
- * The 2 control points are used to define a cubic Bézier curve between 2 anchors
+ * The 2 control points are used to define a cubic Bézier-like curve between 2 anchors
* @param x the next control point's x
* @param y the next control point's y
* @return a CurveBuilderAtControlPoint1 a part of the curve builder system
@@ -28,13 +28,14 @@ public CurveBuilderAtControlPoint1 controlPoint1( float x, float y ){
}
/**
- * Adds a point that the curve will attempt to move towards but may not actually touch.
+ * Adds a point that the curve will attempt to move towards (but may not actually touch)
*
- * The 2 control points are used to define a cubic Bézier curve between 2 anchors
+ * The 2 control points are used to define a cubic Bézier-like curve between 2 anchors
* @param nextControlPoint the control point
* @return a CurveBuilderAtControlPoint1 a part of the curve builder system
*/
public CurveBuilderAtControlPoint1 controlPoint1( Vector2f nextControlPoint ){
+ checkReuse();
return new CurveBuilderAtControlPoint1(curveBeingBuilt, controlPointIn, currentAnchor, nextControlPoint);
}
@@ -54,14 +55,17 @@ public CurveBuilderAtAnchor anchorPoint(float x, float y){
* @return a CurveBuilderAtAnchor a part of the curve builder system
*/
public CurveBuilderAtAnchor anchorPoint(Vector2f nextAnchor ){
+ //no checkReuse() as the call to controlPoint1 will do that
//simulate a straight line using a Bézier curve
Vector2f midOne = currentAnchor.mult(2f/3).add(nextAnchor.mult(1f/3));
Vector2f midTwo = currentAnchor.mult(1f/3).add(nextAnchor.mult(2f/3));
return controlPoint1(midOne).controlPoint2(midTwo).anchorPoint(nextAnchor);
}
- public Curve end(){
+ public Curve build(){
+ checkReuse();
curveBeingBuilt.addControlPoint(controlPointIn, currentAnchor, null);
return curveBeingBuilt;
}
+
}
\ No newline at end of file
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
index 07c939f..741f192 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
@@ -3,7 +3,7 @@
import com.epaga.particles.valuetypes.Curve;
import com.jme3.math.Vector2f;
-public class CurveBuilderAtControlPoint1{
+public class CurveBuilderAtControlPoint1 extends CurveBuilderPiece{
Curve curveBeingBuilt;
@@ -32,6 +32,7 @@ public CurveBuilderAtControlPoint2 controlPoint2( float x, float y ){
* @return a CurveBuilderAtControlPoint1 a part of the curve builder system
*/
public CurveBuilderAtControlPoint2 controlPoint2( Vector2f nextControlPoint ){
+ checkReuse();
return new CurveBuilderAtControlPoint2(curveBeingBuilt, nextControlPoint);
}
}
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
index c0e242e..bd1053f 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
@@ -3,7 +3,7 @@
import com.epaga.particles.valuetypes.Curve;
import com.jme3.math.Vector2f;
-public class CurveBuilderAtControlPoint2{
+public class CurveBuilderAtControlPoint2 extends CurveBuilderPiece{
Curve curveBeingBuilt;
Vector2f inControlPoint;
@@ -33,6 +33,7 @@ public CurveBuilderAtAnchor anchorPoint(float x, float y){
* @return a CurveBuilderAtAnchor a part of the curve builder system
*/
public CurveBuilderAtAnchor anchorPoint(Vector2f nextAnchor ){
+ checkReuse();
return new CurveBuilderAtAnchor(curveBeingBuilt, inControlPoint, nextAnchor);
}
}
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderPiece.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderPiece.java
new file mode 100644
index 0000000..3323106
--- /dev/null
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderPiece.java
@@ -0,0 +1,13 @@
+package com.epaga.particles.valuetypes.curvebuilder;
+
+public class CurveBuilderPiece{
+
+ boolean used = false;
+
+ protected void checkReuse(){
+ if (used){
+ throw new IllegalStateException("Curve builders must not be reused (As they actually build a single curve as they go along)");
+ }
+ used = true;
+ }
+}
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java
index 8e45793..e275066 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderStart.java
@@ -4,7 +4,7 @@
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
-public class CurveBuilderStart{
+public class CurveBuilderStart extends CurveBuilderPiece{
Curve curveBeingBuilt = new Curve();
@@ -17,6 +17,7 @@ public CurveBuilderAtAnchor anchorPoint(float x, float y){
* @return CurveBuilderAtAnchor a part of the curve builder system
*/
public CurveBuilderAtAnchor anchorPoint(Vector2f start){
+ checkReuse();
return new CurveBuilderAtAnchor(curveBeingBuilt, null, start);
}
diff --git a/src/test/java/com/epaga/particles/valuetypes/CurveTest.java b/src/test/java/com/epaga/particles/valuetypes/CurveTest.java
index 10c1b75..d8cf4fa 100644
--- a/src/test/java/com/epaga/particles/valuetypes/CurveTest.java
+++ b/src/test/java/com/epaga/particles/valuetypes/CurveTest.java
@@ -1,5 +1,6 @@
package com.epaga.particles.valuetypes;
+import com.epaga.particles.valuetypes.curvebuilder.CurveBuilderAtAnchor;
import org.junit.Test;
import static org.junit.Assert.*;
@@ -11,7 +12,7 @@ public void builder_straightLine(){
Curve curve = Curve.builder()
.anchorPoint(0,0)
.anchorPoint(1,10)
- .end();
+ .build();
assertEquals(0, curve.getValue(0f), 0.001);
assertEquals(4, curve.getValue(0.4f), 0.001);
@@ -27,7 +28,7 @@ public void builder_doubleStraightLine(){
.anchorPoint(0,0)
.anchorPoint(0.4f,10)
.anchorPoint(1f, 10)
- .end();
+ .build();
assertEquals(0, curve.getValue(0f), 0.001);
assertEquals(5, curve.getValue(0.2f), 0.001);
@@ -48,7 +49,7 @@ public void builder_curve(){
.controlPoint1(0.2f, 1)
.controlPoint2(0.8f, 0)
.anchorPoint(1,1)
- .end();
+ .build();
//expected values obtained using https://www.desmos.com/calculator/ebdtbxgbq0
@@ -71,4 +72,14 @@ public void builder_curve(){
assertEquals(0.5, curve.getValue(0.5f), 0.001);
assertEquals(1, curve.getValue(1), 0.001);
}
-}
\ No newline at end of file
+
+ @Test(expected = IllegalStateException.class)
+ public void builder_reuseLeadsToException(){
+ CurveBuilderAtAnchor builder = Curve.builder()
+ .anchorPoint(0,0);
+
+ Curve legalUse = builder.build();
+ Curve illegalReuse = builder.build();
+ }
+
+}
From 5a65fbaa0b99cdb1332fb10ca43badb767bb49e2 Mon Sep 17 00:00:00 2001
From: Richard Tingle <6330028+richardTingle@users.noreply.github.com>
Date: Sat, 18 Dec 2021 17:00:04 +0000
Subject: [PATCH 6/8] #6 Clean up the curve builder javadocs
---
.../valuetypes/curvebuilder/CurveBuilderAtAnchor.java | 2 +-
.../curvebuilder/CurveBuilderAtControlPoint1.java | 6 +++---
.../curvebuilder/CurveBuilderAtControlPoint2.java | 6 +++---
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
index 6cb3144..f53053e 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtAnchor.java
@@ -56,7 +56,7 @@ public CurveBuilderAtAnchor anchorPoint(float x, float y){
*/
public CurveBuilderAtAnchor anchorPoint(Vector2f nextAnchor ){
//no checkReuse() as the call to controlPoint1 will do that
- //simulate a straight line using a Bézier curve
+ //simulate a straight line using a Bézier-like curve
Vector2f midOne = currentAnchor.mult(2f/3).add(nextAnchor.mult(1f/3));
Vector2f midTwo = currentAnchor.mult(1f/3).add(nextAnchor.mult(2f/3));
return controlPoint1(midOne).controlPoint2(midTwo).anchorPoint(nextAnchor);
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
index 741f192..9afa29a 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint1.java
@@ -13,9 +13,9 @@ public CurveBuilderAtControlPoint1(Curve curveBeingBuilt, Vector2f controlPointI
}
/**
- * Adds a point that the curve will attempt to move towards but may not actually touch.
+ * Adds a point that the curve will attempt to move towards (but may not actually touch).
*
- * The 2 control points are used to define a cubic Bézier curve between 2 anchors
+ * The 2 control points are used to define a cubic Bézier-like curve between 2 anchors
* @param x the control point's x
* @param y the control point's y
* @return a CurveBuilderAtControlPoint1 a part of the curve builder system
@@ -27,7 +27,7 @@ public CurveBuilderAtControlPoint2 controlPoint2( float x, float y ){
/**
* Adds a point that the curve will attempt to move towards (but may not actually touch).
*
- * The 2 control points are used to define a cubic Bézier curve between 2 anchors
+ * The 2 control points are used to define a cubic Bézier-like curve between 2 anchors
* @param nextControlPoint the control point
* @return a CurveBuilderAtControlPoint1 a part of the curve builder system
*/
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
index bd1053f..5caace0 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderAtControlPoint2.java
@@ -16,7 +16,7 @@ public CurveBuilderAtControlPoint2(Curve curveBeingBuilt, Vector2f inControlPoin
/**
* Adds a point that the curve go through.
*
- * Anchors are the starts and ends of cubic Bézier curves
+ * Anchors are the starts and ends of cubic Bézier-like curves
* @param x the anchor point's x
* @param y the anchor point's y
* @return a CurveBuilderAtAnchor a part of the curve builder system
@@ -26,9 +26,9 @@ public CurveBuilderAtAnchor anchorPoint(float x, float y){
}
/**
- * Adds a point that the curve go through.
+ * Adds a point that the curve will go through.
*
- * Anchors are the starts and ends of cubic Bézier curves
+ * Anchors are the starts and ends of cubic Bézier-like curves
* @param nextAnchor the anchor point
* @return a CurveBuilderAtAnchor a part of the curve builder system
*/
From e9b8408ee3910920535218f734433d0ff20d72eb Mon Sep 17 00:00:00 2001
From: Richard Tingle <6330028+richardTingle@users.noreply.github.com>
Date: Sat, 18 Dec 2021 17:03:04 +0000
Subject: [PATCH 7/8] #6 Update classes to follow the coding standards of
particle monkey
---
.../curvebuilder/CurveBuilderPiece.java | 12 +-
.../epaga/particles/valuetypes/CurveTest.java | 148 +++++++++---------
2 files changed, 80 insertions(+), 80 deletions(-)
diff --git a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderPiece.java b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderPiece.java
index 3323106..ff8638c 100644
--- a/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderPiece.java
+++ b/src/main/java/com/epaga/particles/valuetypes/curvebuilder/CurveBuilderPiece.java
@@ -2,12 +2,12 @@
public class CurveBuilderPiece{
- boolean used = false;
+ boolean used = false;
- protected void checkReuse(){
- if (used){
- throw new IllegalStateException("Curve builders must not be reused (As they actually build a single curve as they go along)");
- }
- used = true;
+ protected void checkReuse(){
+ if (used){
+ throw new IllegalStateException("Curve builders must not be reused (As they actually build a single curve as they go along)");
}
+ used = true;
+ }
}
diff --git a/src/test/java/com/epaga/particles/valuetypes/CurveTest.java b/src/test/java/com/epaga/particles/valuetypes/CurveTest.java
index d8cf4fa..0645133 100644
--- a/src/test/java/com/epaga/particles/valuetypes/CurveTest.java
+++ b/src/test/java/com/epaga/particles/valuetypes/CurveTest.java
@@ -7,79 +7,79 @@
public class CurveTest{
- @Test
- public void builder_straightLine(){
- Curve curve = Curve.builder()
- .anchorPoint(0,0)
- .anchorPoint(1,10)
- .build();
-
- assertEquals(0, curve.getValue(0f), 0.001);
- assertEquals(4, curve.getValue(0.4f), 0.001);
- assertEquals(10, curve.getValue(1f), 0.001);
- }
-
- /**
- * Tests that 2 straight lines joined together functions correctly
- */
- @Test
- public void builder_doubleStraightLine(){
- Curve curve = Curve.builder()
- .anchorPoint(0,0)
- .anchorPoint(0.4f,10)
- .anchorPoint(1f, 10)
- .build();
-
- assertEquals(0, curve.getValue(0f), 0.001);
- assertEquals(5, curve.getValue(0.2f), 0.001);
- assertEquals(10, curve.getValue(0.8f), 0.001);
- }
-
- /**
- * Tests that a Bézier-like curve functions correctly
- *
- * (Its not actually a true Bézier curve becuse a Bézier curve can "go backwards" and follows a
- * slightly different path
- */
- @Test
- public void builder_curve(){
-
- Curve curve = Curve.builder()
- .anchorPoint(0,0)
- .controlPoint1(0.2f, 1)
- .controlPoint2(0.8f, 0)
- .anchorPoint(1,1)
- .build();
-
- //expected values obtained using https://www.desmos.com/calculator/ebdtbxgbq0
-
- assertEquals(0, curve.getValue(0f), 0.001);
-
- //value obtained as 0.1 along using the following
- // along line 1 = 0.9 * 0 + 0.1 * 1 = 0.1
- // along line 2 = 0.9 * 1 + 0.1 * 0 = 0.9
- // along line 3 = 0.9 * 0 + 0.1 * 1 = 0.1
-
- //obtain 2 new lines between along line 1 -> along line 2 and along line 2 -> along line 3. Get 0.1 along each one
- //along second order 1 = 0.9 * 0.1 + 0.1 * 0.9 = 0.18
- //along second order 2 = 0.9 * 0.9 + 0.1 * 0.1 = 0.82
-
- //final result is 0.1 along the line between the second order points
- // 0.9 * 0.18 + 0.1 * 0.82
-
- assertEquals(0.244, curve.getValue(0.1f), 0.001);
-
- assertEquals(0.5, curve.getValue(0.5f), 0.001);
- assertEquals(1, curve.getValue(1), 0.001);
- }
-
- @Test(expected = IllegalStateException.class)
- public void builder_reuseLeadsToException(){
- CurveBuilderAtAnchor builder = Curve.builder()
- .anchorPoint(0,0);
-
- Curve legalUse = builder.build();
- Curve illegalReuse = builder.build();
- }
+ @Test
+ public void builder_straightLine(){
+ Curve curve = Curve.builder()
+ .anchorPoint(0,0)
+ .anchorPoint(1,10)
+ .build();
+
+ assertEquals(0, curve.getValue(0f), 0.001);
+ assertEquals(4, curve.getValue(0.4f), 0.001);
+ assertEquals(10, curve.getValue(1f), 0.001);
+ }
+
+ /**
+ * Tests that 2 straight lines joined together functions correctly
+ */
+ @Test
+ public void builder_doubleStraightLine(){
+ Curve curve = Curve.builder()
+ .anchorPoint(0,0)
+ .anchorPoint(0.4f,10)
+ .anchorPoint(1f, 10)
+ .build();
+
+ assertEquals(0, curve.getValue(0f), 0.001);
+ assertEquals(5, curve.getValue(0.2f), 0.001);
+ assertEquals(10, curve.getValue(0.8f), 0.001);
+ }
+
+ /**
+ * Tests that a Bézier-like curve functions correctly
+ *
+ * (Its not actually a true Bézier curve becuse a Bézier curve can "go backwards" and follows a
+ * slightly different path
+ */
+ @Test
+ public void builder_curve(){
+
+ Curve curve = Curve.builder()
+ .anchorPoint(0,0)
+ .controlPoint1(0.2f, 1)
+ .controlPoint2(0.8f, 0)
+ .anchorPoint(1,1)
+ .build();
+
+ //expected values obtained using https://www.desmos.com/calculator/ebdtbxgbq0
+
+ assertEquals(0, curve.getValue(0f), 0.001);
+
+ //value obtained as 0.1 along using the following
+ // along line 1 = 0.9 * 0 + 0.1 * 1 = 0.1
+ // along line 2 = 0.9 * 1 + 0.1 * 0 = 0.9
+ // along line 3 = 0.9 * 0 + 0.1 * 1 = 0.1
+
+ //obtain 2 new lines between along line 1 -> along line 2 and along line 2 -> along line 3. Get 0.1 along each one
+ //along second order 1 = 0.9 * 0.1 + 0.1 * 0.9 = 0.18
+ //along second order 2 = 0.9 * 0.9 + 0.1 * 0.1 = 0.82
+
+ //final result is 0.1 along the line between the second order points
+ // 0.9 * 0.18 + 0.1 * 0.82
+
+ assertEquals(0.244, curve.getValue(0.1f), 0.001);
+
+ assertEquals(0.5, curve.getValue(0.5f), 0.001);
+ assertEquals(1, curve.getValue(1), 0.001);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void builder_reuseLeadsToException(){
+ CurveBuilderAtAnchor builder = Curve.builder()
+ .anchorPoint(0,0);
+
+ Curve legalUse = builder.build();
+ Curve illegalReuse = builder.build();
+ }
}
From aa1a45a6344d00c9175dd4a801b24fc6ee993cf1 Mon Sep 17 00:00:00 2001
From: Richard Tingle <6330028+richardTingle@users.noreply.github.com>
Date: Tue, 21 Dec 2021 11:29:35 +0000
Subject: [PATCH 8/8] #6 Javadocs can't contain > characters
---
src/main/java/com/epaga/particles/valuetypes/Curve.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/epaga/particles/valuetypes/Curve.java b/src/main/java/com/epaga/particles/valuetypes/Curve.java
index 0a7787c..cec34bd 100644
--- a/src/main/java/com/epaga/particles/valuetypes/Curve.java
+++ b/src/main/java/com/epaga/particles/valuetypes/Curve.java
@@ -185,7 +185,7 @@ public boolean equals(Object o) {
* .build();
* }
*
- * This example produces a straight line from (0,0) -> (0.5,0.5), then a cubic Besier curves between (0.5,0.5) -> (1,2) with control points (0.6,0.5) and (0.8,2)
+ * This example produces a straight line from (0,0) to (0.5,0.5), then a cubic Besier curves between (0.5,0.5) to (1,2) with control points (0.6,0.5) and (0.8,2)
*
* Note that a builder should not be reused.
*