sdr 0.7

net.cscott.sdr.calls
Class Position

java.lang.Object
  extended by net.cscott.sdr.calls.Position
All Implemented Interfaces:
Comparable<Position>

public class Position
extends Object
implements Comparable<Position>

Position objects represent the position and orientation of a dancer. The (0,0) coordinate represents the center of the square (or formation), and dancers are nominally at least two units away from each other (although breathing may change this). A zero rotation for 'facing direction' means "facing away from the caller". Positive y is "away from the caller". Positive x is "toward the caller's right". The boy in couple number one starts out at (-1, -3) facing 0. The facing field may not be null; to indicate "rotation unspecified" (for example, for phantoms or when specifying "general lines") use a Rotation with a modulus of 0.


Nested Class Summary
static class Position.Flag
          Various flags describing boolean properties of a Position.
 
Field Summary
 Rotation facing
          Facing direction.
 Set<Position.Flag> flags
          Flags describing the history of this Position.
 Fraction x
          Location.
 Fraction y
          Location.
 
Constructor Summary
  Position(Fraction x, Fraction y, Rotation facing, Position.Flag... flags)
          Create a Position object from the given x and y coordinates, facing Rotation, and Position.Flags.
protected Position(Fraction x, Fraction y, Rotation facing, Set<Position.Flag> flags)
          Create a Position object from the given x and y coordinates, facing Rotation, and the given Set of Position.Flags.
  Position(int x, int y, Rotation facing, Position.Flag... flags)
          Create a Position object with integer-valued x and y coordinates, a Rotation and Position.Flags.
 
Method Summary
 Position addFlags(Position.Flag... flags)
          Return a new Position identical to this one, except with the given flags set.
 int compareTo(Position p)
          Compare two Positions.
 boolean equals(Object o)
           
 boolean equalsIgnoringFlags(Position p)
           
 Position forwardStep(Fraction distance, boolean stepIn)
          Move the given distance in the facing direction, clearing any Position.Flags.
static Position getGrid(int x, int y, Rotation r, Position.Flag... flags)
          Returns a position corresponding to the standard square dance grid. 0,0 is the center of the set, and odd coordinates between -3 and 3 correspond to the standard 4x4 grid.
static Position getGrid(int x, int y, String direction, Position.Flag... flags)
          Returns a position corresponding to the standard square dance grid. 0,0 is the center of the set, and odd coordinates between -3 and 3 correspond to the standard 4x4 grid.
 int hashCode()
           
 Position mirror(boolean mirrorShoulderPass)
          Return a new position, mirrored around the y-axis, including the pass, roll, and sweep flags.
 Position normalize()
          Normalize (restrict to 0-modulus) the rotation of the given position, preserving any Position.Flags.
 Position relocate(Fraction x, Fraction y, Rotation facing)
          Move a Position, preserving its flags.
 String repr()
          Emit an executable representation of this position.
 Fraction roll()
          Return a roll amount from the Position.Flag.ROLL_LEFT and Position.Flag.ROLL_RIGHT Position.Flags set on this Position.
 Position rotateAroundOrigin(ExactRotation rot)
          Rotate this position around the origin by the given amount, preserving any Position.Flags.
 Position setFlags(Collection<Position.Flag> f)
          Return a new Position identical to this one, except with exactly the given flags set.
 Position setFlags(Position.Flag... flags)
          Return a new Position identical to this one, except with exactly the given flags set.
 String shortFlagString()
          Return a short string describing the flags on this position.
 Position sideStep(Fraction distance, boolean stepIn)
          Move the given distance perpendicular to the facing direction, clearing any Position.Flags.
 Fraction sweep()
          Return a sweep amount from the Position.Flag.SWEEP_LEFT and Position.Flag.SWEEP_RIGHT Position.Flags set on this Position.
 String toString()
           
 Position turn(Fraction amount, boolean faceIn)
          Turn in place the given amount, clearing any Position.Flags.
 Position turn(Fraction amount, boolean faceIn, Position reference)
          Turn in place the given amount, clearing any Position.Flags.
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

x

public final Fraction x
Location. Always non-null.


y

public final Fraction y
Location. Always non-null.


facing

public final Rotation facing
Facing direction. Note that facing should always be an ExactRotation for real (non-phantom) dancers.


flags

public final Set<Position.Flag> flags
Flags describing the history of this Position.

Constructor Detail

Position

public Position(Fraction x,
                Fraction y,
                Rotation facing,
                Position.Flag... flags)
Create a Position object from the given x and y coordinates, facing Rotation, and Position.Flags.


Position

public Position(int x,
                int y,
                Rotation facing,
                Position.Flag... flags)
Create a Position object with integer-valued x and y coordinates, a Rotation and Position.Flags.


Position

protected Position(Fraction x,
                   Fraction y,
                   Rotation facing,
                   Set<Position.Flag> flags)
Create a Position object from the given x and y coordinates, facing Rotation, and the given Set of Position.Flags.

Method Detail

forwardStep

public Position forwardStep(Fraction distance,
                            boolean stepIn)
Move the given distance in the facing direction, clearing any Position.Flags. Requires that the facing direction be an ExactRotation. If stepIn is true, the distance is negated if the result would end up closer to the origin for positive distance (stepping "in" towards the center of the formation, or further to the origin for negative distance (stepping "out" away from the center).

Tests:
Move the couple #1 boy forward two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(-1,-3,"n").forwardStep(Fraction.TWO, false)
-1,-1,n
Move the couple #1 boy backward two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(-1,-3,"n").forwardStep(Fraction.TWO.negate(), false)
-1,-5,n
Move the couple #1 boy "in" two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(-1,-3,"n").forwardStep(Fraction.TWO, true)
-1,-1,n
Move the couple #1 boy "out" two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(-1,-3,"n").forwardStep(Fraction.TWO.negate(), true)
-1,-5,n
Couple #2 boy facing out; move forward two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(3,-1,"e").forwardStep(Fraction.TWO, false)
5,-1,e
Couple #2 boy facing out; move backward two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(3,-1,"e").forwardStep(Fraction.TWO.negate(), false)
1,-1,e
Couple #2 boy facing out; move "in" two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(3,-1,"e").forwardStep(Fraction.TWO, true)
1,-1,e
Couple #2 boy facing out; move "out" two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(3,-1,"e").forwardStep(Fraction.TWO.negate(), true)
5,-1,e
Any flags present are cleared.
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ZERO, ExactRotation.ZERO,
  >                  Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT);
0,0,n,[PASS_LEFT, ROLL_RIGHT]
js> p.forwardStep(Fraction.ZERO, false)
0,0,n
Can't step in if there's no clear in direction.
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ONE, Fraction.ZERO, ExactRotation.ZERO);
1,0,n
js> try { p.forwardStep(Fraction.ONE, true); }
  > catch(e) { print(e.javaException); }
net.cscott.sdr.calls.BadCallException: no clear 'in' direction

sideStep

public Position sideStep(Fraction distance,
                         boolean stepIn)
Move the given distance perpendicular to the facing direction, clearing any Position.Flags. Requires that the facing direction be an ExactRotation. If stepIn is true, the distance is negated if the result would end up closer to the origin for positive distance (stepping "in" towards the center of the formation, or further to the origin for negative distance (stepping "out" away from the center).

Tests:
Couple #2 girl move "right" two steps (truck):
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(3,1,"w").sideStep(Fraction.TWO, false)
3,3,w
Couple #1 boy move "left" two steps (truck):
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(-1,-3,"n").sideStep(Fraction.TWO.negate(), false)
-3,-3,n
Couple #1 boy facing west move "in" two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(-1,-3,"w").sideStep(Fraction.TWO, true)
-1,-1,w
Couple #1 boy facing west move "out" two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(-1,-3,"w").sideStep(Fraction.TWO.negate(), true)
-1,-5,w
Couple #1 boy facing east move "out" two steps:
js> importPackage(net.cscott.sdr.util)
js> Position.getGrid(-1,-3,"e").sideStep(Fraction.TWO.negate(), true)
-1,-5,e
Any flags present are cleared.
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ZERO, ExactRotation.ZERO,
  >                  Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT);
0,0,n,[PASS_LEFT, ROLL_RIGHT]
js> p.sideStep(Fraction.ZERO, false)
0,0,n
Can't step in if there's no clear in direction.
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ONE, ExactRotation.ZERO);
0,1,n
js> try { p.sideStep(Fraction.ONE, true); }
  > catch(e) { print(e.javaException); }
net.cscott.sdr.calls.BadCallException: no clear 'in' direction

turn

public Position turn(Fraction amount,
                     boolean faceIn)
Turn in place the given amount, clearing any Position.Flags. If faceIn is true, a positive amount will turn towards the origin; otherwise a positive amount turns clockwise.

Tests:
Exercise the turn method; amounts aren't normalized in order to preserve proper roll/sweep directions:
js> ONE_HALF = net.cscott.sdr.util.Fraction.ONE_HALF
1/2
js> p = Position.getGrid(0,0,"n").turn(ONE_HALF, false)
0,0,s
js> p = p.turn(ONE_HALF, false)
0,0,n
js> p.facing.amount.toProperString()
1
Turning "in" when in is clockwise:
js> importPackage(net.cscott.sdr.util)
js> p = Position.getGrid(1,1,"s").turn(Fraction.ONE_QUARTER, true)
1,1,w
Turning "out" when in is clockwise:
js> importPackage(net.cscott.sdr.util)
js> p = Position.getGrid(1,1,"s").turn(Fraction.ONE_QUARTER.negate(), true)
1,1,e
Turning "in" when in is counter-clockwise:
js> importPackage(net.cscott.sdr.util)
js> p = Position.getGrid(1,1,"n").turn(Fraction.ONE_QUARTER, true)
1,1,w
Turning "out" when in is counter-clockwise:
js> importPackage(net.cscott.sdr.util)
js> p = Position.getGrid(1,1,"n").turn(Fraction.ONE_QUARTER.negate(), true)
1,1,e
Any flags present are cleared.
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ZERO, ExactRotation.ZERO,
  >                  Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT);
0,0,n,[PASS_LEFT, ROLL_RIGHT]
js> p.turn(Fraction.ZERO, false)
0,0,n
Can't face in if facing exactly into the center:
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ONE, Fraction.ONE, ExactRotation.FIVE_EIGHTHS);
1,1,sw
js> try { p = p.turn(Fraction.ONE_QUARTER, true); }
  > catch(e) { print(e.javaException); }
net.cscott.sdr.calls.BadCallException: no clear 'in' direction
Can't face in if facing exactly away from the center:
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ONE, ExactRotation.ZERO);
0,1,n
js> try { p = p.turn(Fraction.ONE_QUARTER, true); }
  > catch(e) { print(e.javaException); }
net.cscott.sdr.calls.BadCallException: no clear 'in' direction
We can face in from some inexact directions:
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ONE, Fraction.ZERO, Rotation.fromAbsoluteString("|"));
1,0,|
js> p = p.turn(Fraction.ONE_QUARTER, true)
1,0,w
js> p = new Position(Fraction.ONE, Fraction.ZERO, Rotation.fromAbsoluteString("|"));
1,0,|
js> p = p.turn(Fraction.ONE_QUARTER.negate(), true)
1,0,e

turn

public Position turn(Fraction amount,
                     boolean faceIn,
                     Position reference)
Turn in place the given amount, clearing any Position.Flags. If faceIn is true, a positive amount will turn towards the origin; otherwise a positive amount turns clockwise.

This version of the method takes an additional argument specifying a point at which to evaluate the "in/out" direction.


setFlags

public Position setFlags(Position.Flag... flags)
Return a new Position identical to this one, except with exactly the given flags set.

Tests:
Set the SWEEP_LEFT and ROLL_RIGHT flags:
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ZERO, ExactRotation.ZERO,
  >                  Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT);
0,0,n,[PASS_LEFT, ROLL_RIGHT]
js> p.setFlags(Position.Flag.ROLL_RIGHT, Position.Flag.SWEEP_LEFT)
0,0,n,[ROLL_RIGHT, SWEEP_LEFT]

setFlags

public Position setFlags(Collection<Position.Flag> f)
Return a new Position identical to this one, except with exactly the given flags set.

See Also:
setFlags(Flag...)

addFlags

public Position addFlags(Position.Flag... flags)
Return a new Position identical to this one, except with the given flags set.

Tests:
Add the SWEEP_LEFT flag:
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ZERO, ExactRotation.ZERO,
  >                  Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT);
0,0,n,[PASS_LEFT, ROLL_RIGHT]
js> p=p.addFlags(Position.Flag.ROLL_RIGHT, Position.Flag.SWEEP_LEFT)
0,0,n,[PASS_LEFT, ROLL_RIGHT, SWEEP_LEFT]
js> p=p.addFlags(Position.Flag.ROLL_RIGHT, Position.Flag.SWEEP_LEFT)
0,0,n,[PASS_LEFT, ROLL_RIGHT, SWEEP_LEFT]

relocate

public Position relocate(Fraction x,
                         Fraction y,
                         Rotation facing)
Move a Position, preserving its flags.

Tests:
Add the SWEEP_LEFT flag:
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ZERO, ExactRotation.ZERO,
  >                  Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT);
0,0,n,[PASS_LEFT, ROLL_RIGHT]
js> p = p.relocate(Fraction.ONE, Fraction.TWO, ExactRotation.ONE_QUARTER);
1,2,e,[PASS_LEFT, ROLL_RIGHT]

roll

public Fraction roll()
Return a roll amount from the Position.Flag.ROLL_LEFT and Position.Flag.ROLL_RIGHT Position.Flags set on this Position.

Tests:
js> p = Position.getGrid(0,0,"n");
0,0,n
js> p.roll();
0/1
js> p = p.addFlags(Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT, Position.Flag.SWEEP_LEFT); 
0,0,n,[PASS_LEFT, ROLL_RIGHT, SWEEP_LEFT]
js> p.roll()
1/4
js> p = p.setFlags(Position.Flag.SWEEP_RIGHT, Position.Flag.ROLL_LEFT)
0,0,n,[ROLL_LEFT, SWEEP_RIGHT]
js> p.roll()
-1/4

sweep

public Fraction sweep()
Return a sweep amount from the Position.Flag.SWEEP_LEFT and Position.Flag.SWEEP_RIGHT Position.Flags set on this Position.

Tests:
js> p = Position.getGrid(0,0,"n");
0,0,n
js> p.sweep();
0/1
js> p = p.addFlags(Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT, Position.Flag.SWEEP_LEFT); 
0,0,n,[PASS_LEFT, ROLL_RIGHT, SWEEP_LEFT]
js> p.sweep()
-1/4
js> p = p.setFlags(Position.Flag.SWEEP_RIGHT, Position.Flag.ROLL_LEFT)
0,0,n,[ROLL_LEFT, SWEEP_RIGHT]
js> p.sweep()
1/4

rotateAroundOrigin

public Position rotateAroundOrigin(ExactRotation rot)
Rotate this position around the origin by the given amount, preserving any Position.Flags.

Tests:
Rotating the #1 boy by 1/4 gives the #4 boy position:
js> p = Position.getGrid(-1,-3,0)
-1,-3,n
js> p = p.setFlags(Position.Flag.PASS_LEFT)
-1,-3,n,[PASS_LEFT]
js> p.rotateAroundOrigin(ExactRotation.ONE_QUARTER)
-3,1,e,[PASS_LEFT]

mirror

public Position mirror(boolean mirrorShoulderPass)
Return a new position, mirrored around the y-axis, including the pass, roll, and sweep flags.

Tests:
js> p=Position.getGrid(1,2,"e",Position.Flag.SWEEP_LEFT,Position.Flag.ROLL_RIGHT);
1,2,e,[ROLL_RIGHT, SWEEP_LEFT]
js> p.mirror(false);
-1,2,w,[ROLL_LEFT, SWEEP_RIGHT]
js> p.mirror(true);
-1,2,w,[PASS_LEFT, ROLL_LEFT, SWEEP_RIGHT]

normalize

public Position normalize()
Normalize (restrict to 0-modulus) the rotation of the given position, preserving any Position.Flags.

Tests:
Show normalization after two 180-degree turns:
js> importPackage(net.cscott.sdr.util)
js> p = Position.getGrid(0,0,"e").turn(Fraction.ONE_HALF, false)
0,0,w
js> p = p.turn(Fraction.ONE_HALF, false)
0,0,e
js> p.facing.amount.toProperString()
1 1/4
js> p = p.setFlags(Position.Flag.PASS_LEFT)
0,0,e,[PASS_LEFT]
js> p = p.normalize()
0,0,e,[PASS_LEFT]
js> p.facing.amount.toProperString()
1/4

getGrid

public static Position getGrid(int x,
                               int y,
                               Rotation r,
                               Position.Flag... flags)
Returns a position corresponding to the standard square dance grid. 0,0 is the center of the set, and odd coordinates between -3 and 3 correspond to the standard 4x4 grid.

Tests:
Some sample grid locations:
js> Position.getGrid(0,0,ExactRotation.ZERO)
0,0,n
js> Position.getGrid(-3,3,ExactRotation.WEST)
-3,3,w

getGrid

public static Position getGrid(int x,
                               int y,
                               String direction,
                               Position.Flag... flags)
Returns a position corresponding to the standard square dance grid. 0,0 is the center of the set, and odd coordinates between -3 and 3 correspond to the standard 4x4 grid. For convenience, the direction is specified as a string valid for ExactRotation.valueOf(String).

Tests:
Some sample grid locations:
js> Position.getGrid(0,0,"n")
0,0,n
js> Position.getGrid(1,2,"e")
1,2,e

equals

public boolean equals(Object o)
Overrides:
equals in class Object

equalsIgnoringFlags

public boolean equalsIgnoringFlags(Position p)

hashCode

public int hashCode()
Overrides:
hashCode in class Object

toString

public String toString()
Overrides:
toString in class Object

shortFlagString

public String shortFlagString()
Return a short string describing the flags on this position.

Tests:
js> p=Position.getGrid(1,2,"e",Position.Flag.SWEEP_LEFT,Position.Flag.ROLL_RIGHT);
1,2,e,[ROLL_RIGHT, SWEEP_LEFT]
js> new String(p.shortFlagString()).toSource()
(new String("RL"))
js> p = p.addFlags(Position.Flag.PASS_LEFT)
1,2,e,[PASS_LEFT, ROLL_RIGHT, SWEEP_LEFT]
js> new String(p.shortFlagString()).toSource()
(new String("rl"))
js> p = p.setFlags(Position.Flag.PASS_LEFT, Position.Flag.ROLL_LEFT)
1,2,e,[PASS_LEFT, ROLL_LEFT]
js> new String(p.shortFlagString()).toSource()
(new String("l_"))
js> p = p.setFlags(Position.Flag.PASS_LEFT)
1,2,e,[PASS_LEFT]
js> new String(p.shortFlagString()).toSource()
(new String("__"))
js> p = p.addFlags(Position.Flag.SWEEP_RIGHT)
1,2,e,[PASS_LEFT, SWEEP_RIGHT]
js> new String(p.shortFlagString()).toSource()
(new String("_r"))
js> p = p.setFlags(Position.Flag.SWEEP_RIGHT)
1,2,e,[SWEEP_RIGHT]
js> new String(p.shortFlagString()).toSource()
(new String(" R"))
js> p = p.setFlags()
1,2,e
js> new String(p.shortFlagString()).toSource()
(new String("  "))

repr

public String repr()
Emit an executable representation of this position.

Tests:
js> importPackage(net.cscott.sdr.util)
js> p = new Position(Fraction.ZERO, Fraction.ONE_HALF, ExactRotation.ONE_EIGHTH,
  >                  Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT);
0,1/2,ne,[PASS_LEFT, ROLL_RIGHT]
js> p.repr()
new Position(Fraction.valueOf(0), Fraction.valueOf(1,2), ExactRotation.ONE_EIGHTH, Position.Flag.PASS_LEFT, Position.Flag.ROLL_RIGHT)

compareTo

public int compareTo(Position p)
Compare two Positions. We use reading order: top to bottom, then left to right. Ties are broken first by facing direction: first the most specific rotation modulus, then by normalized direction. Remaining ties are broken by comparing the flag sets.

Specified by:
compareTo in interface Comparable<Position>
Tests:
Top to bottom:
js> Position.getGrid(0,0,"n").compareTo(Position.getGrid(1,1,"n")) > 0
true
Left to right:
js> Position.getGrid(1,0,"n").compareTo(Position.getGrid(0,0,"n")) > 0
true
Most specific rotation modulus first:
js> new Position["(int,int,net.cscott.sdr.calls.Rotation,net.cscott.sdr.calls.Position$Flag[])"](
  >              0,0,Rotation.fromAbsoluteString("|")
  >              ).compareTo(Position.getGrid(0,0,"n")) > 0
true
Break ties by comparing position flags:
js> Position.getGrid(1,2,"e").compareTo(Position.getGrid(1,2,"e",Position.Flag.PASS_LEFT)) != 0
true
Normalized direction:
js> Position.getGrid(0,0,"e").compareTo(Position.getGrid(0,0,"n")) > 0
true
Equality:
js> Position.getGrid(1,2,"w").compareTo(Position.getGrid(1,2,"w")) == 0
true

sdr 0.7

Copyright © 2006-2009 C. Scott Ananian