summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2014-01-17 11:37:34 +0100
committerPeter Wu <lekensteyn@gmail.com>2014-01-17 11:37:34 +0100
commitfe257bbd8b9304578c38ee3e386c8a4660f8589e (patch)
tree4b82cab18de0bf7d4fc1193ef15d7cdd90f42334
parent64557243f267076c030644279b531cf6e7932e86 (diff)
download2iv60-robots-fe257bbd8b9304578c38ee3e386c8a4660f8589e.tar.gz
Hook up O track drawing
New bugs: with the O track, the robots look in the wrong direction.
-rw-r--r--src/RaceTrack.java93
1 files changed, 80 insertions, 13 deletions
diff --git a/src/RaceTrack.java b/src/RaceTrack.java
index 3828d54..5c5b842 100644
--- a/src/RaceTrack.java
+++ b/src/RaceTrack.java
@@ -96,34 +96,78 @@ class RaceTrack extends BetterBase {
public void draw(int trackNr) {
// The test track is selected
if (0 == trackNr) {
- drawTestTrack();
+ // Special case: no control points, fall back to test track.
+ selectedControlPoints = null;
} else if (1 == trackNr) { // The O-track is selected
- drawTrack(controlPointsOTrack);
+ selectedControlPoints = controlPointsOTrack;
} else if (2 == trackNr) { // The L-track is selected
- drawTrack(controlPointsLTrack);
+ selectedControlPoints = controlPointsLTrack;
} else if (3 == trackNr) { // The C-track is selected
- drawTrack(controlPointsCTrack);
+ selectedControlPoints = controlPointsCTrack;
} else if (4 == trackNr) { // The custom track is selected
- drawTrack(controlPointsOTrack);
+ selectedControlPoints = controlPointsCustomTrack;
}
+ if (selectedControlPoints != null) {
+ assert selectedControlPoints.length % 3 == 0 :
+ "Multiple of three control points required";
+ }
+ drawTrack();
+ }
+
+ /**
+ * For internal use, only valid for drawing Bézier splines.
+ */
+ private int bezier_start_i;
+
+ private double calculateBezierParams(double t) {
+ t = t % 1.0;
+ //assert t >= 0 && t < 1.0 : "t is invalid: " + t;
+
+ int number_of_segments = selectedControlPoints.length / 3;
+ // number of "u" units per segment
+ double segment_size = 1.0 / number_of_segments;
+
+ int segment_number = (int) (t / segment_size);
+ // should always hold if t < 1.0
+ assert segment_number < number_of_segments;
+ bezier_start_i = 3 * segment_number;
+
+ // drop segments before this one
+ double segment_u = t - segment_number * segment_size;
+ // scale the part to 0.0 to 0.1
+ segment_u *= number_of_segments;
+ assert segment_u >= 0.0 && segment_u <= 1.0;
+ return segment_u;
}
/**
* Returns the position of the curve at 0 <= {@code t} <= 1.
*/
public Vector getPoint(double t) {
+ if (selectedControlPoints != null) {
+ // TODO: do not call func -- optimization
+ double u = calculateBezierParams(t);
+ return getCubicBezierPnt(u, selectedControlPoints, bezier_start_i);
+ }
return new Vector(ELLIPSE_A * cos(2 * PI * t),
ELLIPSE_B * sin(2 * PI * t),
1);
}
+ private int getNumberOfLanes() {
+ // TODO: get robots count from race instance
+ return 4;
+ }
+
/**
* Returns the position of the curve at 0 &lt;= {@code t} &lt;= 1 and
* the center of a lane at lane 1 &lt;= laneNo &lt;= (number of robots).
*/
public Vector getPointForLane(double t, double laneNo) {
Vector p = getPoint(t);
- Vector lanes_len = new Vector(p.x(), p.y(), 0).normalized().scale(laneNo + .5);
+ // relative distance from center line (positive if directed to normal)
+ double relDist = laneNo - getNumberOfLanes() / 2 + .5;
+ Vector lanes_len = getNormal(t).scale(relDist);
return p.add(lanes_len);
}
@@ -131,6 +175,12 @@ class RaceTrack extends BetterBase {
* Returns the tangent of the curve at 0 <= {@code t} <= 1.
*/
public Vector getTangent(double t) {
+ if (selectedControlPoints != null) {
+ // TODO: do not call func -- optimization
+ double u = calculateBezierParams(t);
+ return getCubicBezierTng(u, selectedControlPoints, bezier_start_i);
+ }
+
/*
* Given a vector (-Y/B^2, X/A^2, 0) where X and Y are the coordinates
* of the point p on the ellipse. A is the HALFWIDTH of the ellipse and
@@ -153,35 +203,52 @@ class RaceTrack extends BetterBase {
0).normalized();
}
- private void drawTestTrack() {
+ /**
+ * Returns the normal vector of the curve at t.
+ */
+ public Vector getNormal(double t) {
+ Vector tangent = getTangent(t);
+ // right-hand rule: a (tangent direction), a x b is normal (pointing
+ // outside), so b must be positive Z vector.
+ Vector norm = tangent.cross(Vector.Z);
+ // for out purposes, Z is zero.
+ assert norm.z() == 0 : "Z is not zero!";
+ assert tangent.dot(norm) == 0 : "Result is not normal?!";
+ // just to be sure, unit lengths!
+ return norm.normalized();
+ }
+
+ private void drawTrack() {
/* A track segment looks like:
* B----------------------------D "outside top"
* / : /|
* / G- - - - - - - - - - - - -/--H "outside bottom"
+ * P
* / /
* A----------------------------C "inside top"
* | |
* E----------------------------F "inside bottom"
* ^-- t = t0 ^-- t = t0 + 1
* Assume point A the inner point of the race track. Draw quads from
- * EF (starting point) to AC, BD, GH.
+ * EF (starting point) to AC, BD, GH. P is a point on the center line.
*/
// previous points
Vector point_A = null, point_B = null, point_E = null, point_G = null;
for (double i = 0; i <= SEGMENTS; ++i) {
double t = i / SEGMENTS;
- Vector point_C = getPoint(t);
- // the outer side is located on the number of lanes (4) shifted from
- // the center to the side (minus 0.5).
- Vector point_D = getPointForLane(t, 3.5);
+ Vector point_P = getPoint(t);
+ Vector norm_P = getNormal(t);
+ Vector halfLaneLen = norm_P.scale(getNumberOfLanes() / 2);
+ Vector point_C = point_P.subtract(halfLaneLen);
+ Vector point_D = point_P.add(halfLaneLen);
// Z=1 to Z=-1
Vector point_F = point_C.subtract(new Vector(0, 0, 2));
Vector point_H = point_D.subtract(new Vector(0, 0, 2));
// initially, there are no "previous" vectors to use as start.
if (i > 0) {
- Vector norm_outside = new Vector(point_E.x(), point_E.y(), 0).normalized();
+ Vector norm_outside = norm_P;
Vector norm_inside = norm_outside.scale(-1).normalized();
Vector norm_up = Vector.Z;