Package: com.multiversesocial.hyperview
Class: com.multiversesocial.hyperview.Spline
Source: src/com/multiversesocial/hyperview/Spline.java
A path a Gob travels along. V3.2: a real curve, followed in floating point. A Spline holds double control points, a curve type (CURVE_LINEAR, CURVE_BEZIER, CURVE_CATMULL_ROM), a speed in pixels per frame and the end logic in its flags. Give it to a Gob with Gob.attachSpline(); HyperView.run() then calls step(gob) once per display frame, which moves the Gob’s exact position fx,fy (doubles) along the curve; the Gob’s integer x,y are those rounded.
Before 3.2 the constructor copied the points into x[] y[] z[] and, for CURVE_BEZIER, computed control points ctrlX/ctrlY which nothing ever read; CURVE_CATMULL_ROM was only a number stored in curveType. HyperView.run() moved the Gob from point to point with integer deltas dX/dY that computeDeltas() took from Octant.getOctant() (one of 8 directions, ±velocity per axis) — so every curve type travelled the same straight, octant snapped segments. Only the optional path line (PATH_LINE_ENA) was drawn from samples, which is why the curves looked curved on screen but the Gob did not follow them.
samplingResolution, default 128 samples, 4 chords each) into a cumulative length table; getPointAtLength(s) inverts it by binary search. The Gob moves speed pixels per frame ALONG the curve: constant speed whatever the spacing of the points (measured ±0.5% per frame step on the test paths).flags. createCircle/createEllipse used to set the z flag but no end logic.x y z dX dY dZ fX.. rX.. targetX.. curPoint velocity are kept and filled for old readers, but the Gob follows the double curve; changing x[] directly no longer moves the Gob (use setPoints / translate / scale / addPoint). A Spline of length 0 never moves its Gob. One Spline can belong to one Gob only.public class Spline implements SplineConstants
| Declaration | Value / initializer | Description | Source |
|---|---|---|---|
public int[] acceleration | No comment in source. | ||
public static final int ADV_ARRIVED | = 1 | moved along the path | |
public static final int ADV_FINISHED | = 3 | was already parked at the end, nothing happened | |
public static final int ADV_MOVING | = 0 | advance() / step() results | |
public static final int ADV_PARKED | = 2 | reached the end this frame and stays there (COLLIDE_AT_END) | |
private boolean closed | = false | control points (floating point) | |
public int curPoint | = 0 | end of the current segment (rounded) | |
public int curRadius | = 1 | No comment in source. | |
public static final int CURVE_BEZIER | = 1 | No comment in source. | |
public static final int CURVE_CATMULL_ROM | = 2 | No comment in source. | |
public static final int CURVE_LINEAR | = 0 | Curve Types | |
private int curveType | = CURVE_LINEAR | No comment in source. | |
public HyperView curView | = null | Core Fields | |
private boolean customHandles | = false | Bezier handles per segment (second) | |
private double[] cx | floating point path | ||
private double[] cy | floating point path | ||
private double[] cz | floating point path | ||
public int deltaX | = 1 | No comment in source. | |
public int deltaY | = 1 | No comment in source. | |
private int dir | = 1 | arc length travelled from the start | |
private double distance | = 0.0 | pixels per frame along the curve | |
public int[] dX | No comment in source. | ||
public int[] dY | No comment in source. | ||
public int[] dZ | No comment in source. | ||
public int[] fDX | No comment in source. | ||
public int[] fDY | No comment in source. | ||
public int[] fDZ | No comment in source. | ||
public int fGPen | = 1 | No comment in source. | |
public int flags | = 0 | index of the current segment's first point | |
public int[] fOctant | Reverse values | ||
public int[] fX | Bounce arrays (legacy, filled but not used by the stepper) | ||
public int[] fY | Bounce arrays (legacy, filled but not used by the stepper) | ||
public int[] fZ | Bounce arrays (legacy, filled but not used by the stepper) | ||
private double[] h1x | rounded samples for drawing (lazy) | ||
private double[] h1y | rounded samples for drawing (lazy) | ||
private double[] h1z | rounded samples for drawing (lazy) | ||
private double[] h2x | Bezier handles per segment (first) | ||
private double[] h2y | Bezier handles per segment (first) | ||
private double[] h2z | Bezier handles per segment (first) | ||
private static final int LEN_SUB | = 4 | arc length table samples per segment | |
private double length | = 0.0 | number of segments | |
public Color lineColor | = Color.white | No comment in source. | |
public byte mapType | = 0 | Spline properties | |
public int mass | = 1 | speed in pixels per frame (int view of speed) | |
public int maximumX | = 0 | Path bounds | |
public int maximumY | = 0 | No comment in source. | |
public int minimumX | = 0x7fffffff | No comment in source. | |
public int minimumY | = 0x7fffffff | No comment in source. | |
public Spline next | = null | No comment in source. | |
Gob owner | = null | the Gob following this Spline (set by Gob.attachSpline) | |
private boolean parked | = false | +1 forward, -1 backward | |
private static final int PATH_DIV | = 24 | chords per sample interval when measuring its length | |
public int pathOffsetX | = 0 | PATH_LINE_ENA draws the path shifted by this (e.g. half the Gob size) | |
public int pathOffsetY | = 0 | PATH_LINE_ENA draws the path shifted by this (e.g. half the Gob size) | |
private int[] pathX | arc length at sample k (k = 0 .. segs*res) | ||
private int[] pathY | arc length at sample k (k = 0 .. segs*res) | ||
public Spline prev | = null | No comment in source. | |
public int[] rDX | No comment in source. | ||
public int[] rDY | No comment in source. | ||
public int[] rDZ | No comment in source. | ||
public int[] rOctant | No comment in source. | ||
public int[] rX | No comment in source. | ||
public int[] rY | No comment in source. | ||
public int[] rZ | No comment in source. | ||
private int samplingResolution | = 128 | arc length table samples per segment | |
private int segs | = 0 | polyline points per segment for getPathX()/getPathY() | |
private double speed | = 1.0 | pixels per frame along the curve | |
public int targetX | = 0 | Movement state | |
public int targetY | = 0 | Movement state | |
public int targetZ | = 0 | Movement state | |
private double[] tLen | total arc length (x,y) | ||
private final double[] tmp | = new double[3] | No comment in source. | |
public int totalPoints | = 0 | Path data (rounded copies of the control points, kept for old readers; see the header) | |
public int velocity | = 1 | speed in pixels per frame (int view of speed) | |
public int[] x | No comment in source. | ||
public int[] y | No comment in source. | ||
public int[] z | No comment in source. |
| Signature | Description | Source |
|---|---|---|
public Spline() | An empty Spline without points; give it points with setPoints(). | |
public Spline(HyperView tView, double tSpeed, double[] tx, double[] ty, double[] tz, int curveType, int flags) | Master constructor. Floating point control points tx,ty (and tz, or null for z = 1), speed tSpeed pixels per frame along the curve, curveType CURVE_LINEAR / CURVE_BEZIER / CURVE_CATMULL_ROM, flags = SplineConstants bits (one of STOP_AT_END, BOUNCE_AT_END, WRAP_AT_END, COLLIDE_AT_END, plus SP_ZBUFFER_ENA, PATH_LINE_ENA ...). The arc length table is built here. | |
public Spline(HyperView tView, int tV, int[] tx, int[] ty) | Legacy int constructor: speed tV pixels per frame, 2D or 3D integer points (z = 1 when omitted); builds the same floating point curve as the master constructor (curve type linear unless given). | |
public Spline(HyperView tView, int tV, int[] tx, int[] ty, int flags) | Legacy int constructor: speed tV pixels per frame, 2D or 3D integer points (z = 1 when omitted); builds the same floating point curve as the master constructor (curve type linear unless given). | |
public Spline(HyperView tView, int tV, int[] tx, int[] ty, int curveType, boolean isCurve) | Legacy int constructor: speed tV pixels per frame, 2D or 3D integer points (z = 1 when omitted); builds the same floating point curve as the master constructor (curve type linear unless given). | |
public Spline(HyperView tView, int tV, int[] tx, int[] ty, int[] tz, int flags) | Legacy int constructor: speed tV pixels per frame, 2D or 3D integer points (z = 1 when omitted); builds the same floating point curve as the master constructor (curve type linear unless given). | |
public Spline(HyperView tView, int tV, int[] tx, int[] ty, int[] tz, int curveType, boolean isCurve) | Legacy int constructor: speed tV pixels per frame, 2D or 3D integer points (z = 1 when omitted); builds the same floating point curve as the master constructor (curve type linear unless given). | |
public Spline(HyperView tView, int tV, int[] tx, int[] ty, int[] tz, int curveType, int flags) | Legacy int constructor: speed tV pixels per frame, 2D or 3D integer points (z = 1 when omitted); builds the same floating point curve as the master constructor (curve type linear unless given). |
| Signature | Description | Source |
|---|---|---|
public void addPoint(double px, double py, double pz) | Append a control point and rebuild the curve (the distance travelled is kept). | |
public void addPoint(int px, int py) | Append a control point (z = 1); see addPoint(double,double,double). | |
public void addPoint(int px, int py, int pz) | Append a control point. | |
public int advance() | Advance one frame: the distance changes by speed (backwards when dir is -1) and the END logic is applied. Does not touch a Gob (see step()). Returns ADV_MOVING, ADV_ARRIVED, ADV_PARKED or ADV_FINISHED. End modes (flags & END_LOGIC), applied with the overshoot carried over, so the speed stays constant through the turn: WRAP_AT_END d -= length (d += length when going backwards): the Gob re-enters at the other end. A closed Spline is seamless, an open one jumps. BOUNCE_AT_END d = 2*length - d, direction reverses (SP_FORWARD follows it); the same at 0. COLLIDE_AT_END d = length (or 0), flags ARRIVED, the Gob stays on the end point and keeps its Spline (the CollisionManager tests it every frame). Alone it is the "park" mode; with WRAP or BOUNCE the Gob keeps moving and is simply a collision participant. STOP_AT_END or none: d = end point, ARRIVED, ADV_FINISHED: step() then detaches the ... | |
public int advance(double ds) | Same with an explicit step ds (pixels, >= 0) instead of the speed. | |
private void autoHandles() | Handles of CURVE_BEZIER: tangent at point j = direction of (P[j+1] - P[j-1]); handle length = chord / 3. | |
private void buildCurve() | No comment in source. | |
private static double clampBetween(double v, double a, double b) | No comment in source. | |
public void cleanUp() | Release the arrays and the references; the Spline can not be used afterwards. | |
public void computeDeltas() | Refresh the legacy int arrays dX/dY/dZ and octants (old readers only: the Gob does not follow them any more). | |
public void computeRDeltas() | Same for the reverse (rDX, rDY, rOctant) arrays. | |
public static Spline createCircle(HyperView view, int cx, int cy, int radius, int points, int speed) | A closed circle of radius pixels round cx,cy through points points (CURVE_BEZIER), speed pixels per frame. Flags WRAP_AT_END | SP_ZBUFFER_ENA: it loops seamlessly and z swings 10 -/+ 4 (nearest at the bottom). Before 3.2 it set the z flag but no end logic. | |
public static Spline createCircle(HyperView view, int cx, int cy, int radius, int points, int speed, int flags) | The same with explicit flags (replace the defaults completely, e.g. WRAP_AT_END alone for a circle of constant size, or COLLIDE_AT_END). | |
public static Spline createEllipse(HyperView view, int cx, int cy, int rx, int ry, int points, int speed) | A closed ellipse (radii rx, ry) round cx,cy, same defaults as createCircle: WRAP_AT_END | SP_ZBUFFER_ENA. The speed is the same all round the ellipse. | |
public static Spline createEllipse(HyperView view, int cx, int cy, int rx, int ry, int points, int speed, int flags) | The same with explicit flags (they replace the defaults). | |
public static Spline createHeart(HyperView view, int cx, int cy, int size, int speed) | A closed heart shape (32 points, CURVE_BEZIER) round cx,cy, size = half the width in pixels. Default end logic WRAP_AT_END; no z. | |
public static Spline createHeart(HyperView view, int cx, int cy, int size, int speed, int flags) | The same with explicit flags (they replace WRAP_AT_END). | |
public static Spline createSpiral(HyperView view, int cx, int cy, int startR, int endR, int turns, int points, int speed) | An open spiral from radius startR to endR with turns turns (CURVE_BEZIER). Default end logic BOUNCE_AT_END: out and back again. | |
public static Spline createSpiral(HyperView view, int cx, int cy, int startR, int endR, int turns, int points, int speed, int flags) | The same with explicit flags (they replace BOUNCE_AT_END). | |
private int endAt(double pos, boolean collide) | No comment in source. | |
private void evalSegment(int seg, double t, double[] out) | No comment in source. | |
private void evalU(double u, double[] out) | curve at u = segment + t (0 .. segs) | |
public double[] getArcLengthTable() | A copy of the arc length table: entry k = pixels from the start to sample k (non decreasing, last = length). | |
public void getControlPoint(int i, double[] out) | Control point i (floating point): out[0]=x, out[1]=y, out[2]=z. | |
public int getCurrentPoint() | Index of the control point at the start of the current segment (legacy; see getSegmentCount, getDistance). | |
public int getCurrentX() | The path position now, rounded (the Gob's x,y while this Spline drives it). | |
public int getCurrentY() | The path y now, rounded. | |
public int getCurrentZ() | The path z now, rounded. | |
public int getCurveType() | CURVE_LINEAR, CURVE_BEZIER or CURVE_CATMULL_ROM. | |
public int getDirection() | +1 while travelling from the first point to the last, -1 backwards (BOUNCE_AT_END, reverse()). | |
public double getDistance() | Pixels travelled from the start of the path. | |
public String getFlagString() | The set Spline flag bits as text (SP_FORWARD|WRAP_AT_END ...), for debugging and the Info steps. | |
public double getLength() | Total arc length of the curve in pixels (measured in x,y). | |
public Gob getOwner() | The Gob which follows this Spline, or null. | |
public int getPathLength() | Number of entries of getPathX()/getPathY(). | |
public int[] getPathX() | x of the curve samples rounded to int pixels (for drawing the path); do not modify. | |
public int[] getPathY() | y of the curve samples rounded to int pixels (for drawing the path); do not modify. | |
public void getPointAtLength(double s, double[] out) | The point s pixels along the curve (s clamped to 0..length): out[0]=x, out[1]=y, out[2]=z. | |
public void getPointOnSegment(int seg, double t, double[] out) | The curve inside segment seg (0 .. getSegmentCount()-1) at t in [0,1]: out[0]=x, out[1]=y, out[2]=z. t=0 is the segment's first control point and t=1 its second (the next one; the first for the closing segment of a closed Spline). This is the plain curve parameter, not arc length. | |
public void getPoint(double[] out) | The point at the current distance: out[0]=x, out[1]=y, out[2]=z. | |
public double getProgress() | Fraction of the path travelled, 0..1. | |
public int getSamplingResolution() | Samples per segment of the arc length table. | |
public int getSegmentCount() | Number of curve segments: points-1, or points for a closed Spline, 0 for a single point. | |
public double getSpeed() | Speed in pixels per frame along the curve. | |
public void getStart(double[] out) | Where the Gob starts: the first point of the path (x,y,z of getPointAtLength(0)). | |
public int getTargetX() | Legacy: x of the end of the current segment (rounded). | |
public int getTargetY() | Legacy: y of the end of the current segment (rounded). | |
public int getTargetZ() | Legacy: z of the end of the current segment (rounded). | |
public int getTotalPoints() | Number of control points. | |
private int idx(int i) | No comment in source. | |
private void initBounceArrays() | No comment in source. | |
private boolean isClosedEff() | No comment in source. | |
public boolean isClosed() | No comment in source. | |
public boolean isParked() | True if the Spline is parked on its end point (COLLIDE_AT_END arrived). | |
private double locate(double s) | largest sample index k <= segs*res-1 with tLen[k] <= s; frac = position inside [k,k+1] | |
private void makePath() | a polyline of the curve for drawing: PATH_DIV points per segment (and the end point) | |
private void pointsChanged() | Rebuild everything derived from the control points (legacy int arrays, curve, length table). | |
public void reset() | Back to the first point: distance 0, direction forward, no longer parked, ARRIVED cleared. | |
public void reverse() | Run the path the other way from where the Gob is now (the direction flips and SP_FORWARD follows, the Gob does not jump); clears the parked state. | |
public void scale(double factor) | Scale x, y and z of all control points by factor; the speed is not changed, so the length scales, and the fraction of the path travelled is kept. | |
public void setBezierHandles(double[] c1x, double[] c1y, double[] c2x, double[] c2y) | CURVE_BEZIER with your own handles: for segment i (point i to point i+1, getSegmentCount() entries) c1 is the handle after point i and c2 the handle before point i+1, in x,y. z uses straight thirds. The arrays are copied. setCurveType()/setClosed()/setPoints() go back to the automatic handles. | |
public void setClosed(boolean c) | A closed Spline has a last segment from the final point back to the first (3 or more points). | |
public void setCurveType(int type) | Change the curve type (CURVE_LINEAR, CURVE_BEZIER, CURVE_CATMULL_ROM) and rebuild the curve; the distance travelled is kept. | |
public void setDistance(double d) | Put the travelled distance anywhere on the path (clamped to 0..length). Clears the parked state. | |
public void setLineColor(Color color) | Colour of the path line drawn when PATH_LINE_ENA is set. | |
public void setPoints(double[] tx, double[] ty, double[] tz) | Replace the control points (copied; tz may be null = z 1). The travelled distance restarts at 0. | |
public void setSamplingResolution(int resolution) | Samples per segment of the arc length table (at least 4, default 128); the curve is rebuilt. More samples = more exact constant speed. | |
public void setSpeed(double pixelsPerFrame) | Set the speed (pixels per frame, floating point; also sets the int velocity). | |
public void setTarget(int tx, int ty, int tz) | Legacy: sets targetX/Y/Z only; the Gob does not use them any more. | |
public void setVelocity(int newVelocity) | Legacy int speed in pixels per frame; same as setSpeed(double). | |
public void setView(HyperView tView) | The HyperView this Spline belongs to. | |
public boolean step(Gob g) | HyperView.run() calls this once per display frame for the Gob that follows this Spline: advance() and write the position. The Gob's float position (fx,fy,fz) is the curve point; x,y,z are those rounded (z only when SP_ZBUFFER_ENA). Returns false when the Gob has let go of the Spline (STOP_AT_END). | |
private void syncLegacy() | curPoint / targetX.. for old readers | |
private static double[] toDouble(int[] a) | No comment in source. | |
public String toString() | STRING REPRESENTATION | |
public void translate(double dx, double dy, double dz) | Move all control points by dx,dy,dz (floating point); the distance travelled is kept. | |
public void translate(int dx, int dy) | Move all control points by dx,dy. | |
public void translate(int dx, int dy, int dz) | Move all control points by dx,dy,dz. | |
public void updateBounds() | Recompute minimumX/Y and maximumX/Y of the control points. | |
public void ZBufferDisable() | Clear SP_ZBUFFER_ENA. | |
public void ZBufferEna() | Set SP_ZBUFFER_ENA: the Gob follows the z of the path and its size = widthBase / z. |
// a curved path, constant speed 4 px/frame, bouncing at the ends
double x[] = {50,170,290,410,530,590};
double y[] = {360,170,360,170,360,250};
Spline s = new Spline(view,4.0,x,y,null,Spline.CURVE_BEZIER,SplineConstants.BOUNCE_AT_END);
s.flags |= SplineConstants.PATH_LINE_ENA; // draw the curve (optional)
Gob g = new Gob(view,"ea2.gif",46,47,GOB_ON_DISPLAY);
view.addGob(g);
g.attachSpline(s); // g now follows the curve; g.getSpline() == s
...
g.detachSpline(); // lets go where it is
// a closed circle that loops forever, at constant size
Spline c = Spline.createCircle(view,320,240,120,36,5,SplineConstants.WRAP_AT_END);
// the exact position (doubles) and the rounded one
double fx = g.getFloatX(), fy = g.getFloatY(); // g.x == Math.round(fx)