sdr 0.5

net.cscott.sdr.calls
Class Breather

java.lang.Object
  extended by net.cscott.sdr.calls.Breather

public class Breather
extends Object

The Breather class contains methods to reassemble and breathe formations.

The insert() method pushes sub-formations into a meta-formation after performing (say) a four person call — ie, starting with a tidal wave, Selector will pull out two four-person waves as a mini-wave as the meta-formation. We do a crossfire (say) from the mini-waves to get boxes. Now insert(Formation,Map) will shove the boxes into the mini-wave meta-formation to get parallel ocean waves.

The breathe() method is a part of insert() which is useful in its own right: it takes a Formation (or a list of Breather.FormationPieces) and breathes it in or out to normalize the spacing between dancers. For example, after "trailers extend" from boxes, we need to make room for the resulting mini-wave in the center. If the ends then u-turn back and everyone extends again, the formation has to squeeze in again to erase the space.

Theory of breathing

First: identify collisions. Collided dancers are inserted into a miniwave which replaces them in the remainder of the algorithm. Second: resolve overlaps. Dancers which overlap have their boundaries adjusted so that they share a boundary at the midpoint of the overlap. Order the resolution from "closest" overlapping dancers to "furthest apart" (smallest overlap), and secondarily from center out, so that extreme overlaps (ie, dancers spaced 1/4 apart) are handled sanely. Third: Sort and order the boundary coordinates, and then allocate space between boundaries so that it is "just enough" to fit the dancers between them. If a dancer spans multiple boundary points, their allocation is divided equally between them. Finally, the output formations are relocated so that they are centered between their new boundaries.

Version:
$Id: Breather.java,v 1.10 2006-10-30 22:09:29 cananian Exp $
Author:
C. Scott Ananian

Nested Class Summary
static class Breather.FormationPiece
           
 
Constructor Summary
Breather()
           
 
Method Summary
static Formation breathe(Formation f)
          Create a canonical formation by compressing the given one.
static Formation breathe(List<Breather.FormationPiece> pieces)
          Take a set of input formation pieces and substitute the given output formation pieces for them, breathing the result together so that the formation is compact.
static Formation insert(Formation meta, Map<Dancer,Formation> components)
          Insert formations into a meta-formation.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

Breather

public Breather()
Method Detail

insert

public static Formation insert(Formation meta,
                               Map<Dancer,Formation> components)
Insert formations into a meta-formation. This reassembles the formation after we've decomposed it into (say) boxes to do a four-person call.

Tests:
Insert COUPLEs, then TANDEMs into a RH_OCEAN_WAVE. Then, for a challenge, insert TANDEMs into a DIAMOND to give a t-bone column:
js> function xofy(meta, f) {
  >   var i=0
  >   var m=new java.util.LinkedHashMap()
  >   for (d in Iterator(meta.sortedDancers())) {
  >     var mm=new java.util.LinkedHashMap()
  >     for (dd in Iterator(f.sortedDancers())) {
  >       mm.put(dd, StandardDancer.values()[i++])
  >     }
  >     m.put(d, new Formation(f, mm))
  >     print(m.get(d).toStringDiagram())
  >   }
  >   return m
  > }
js> meta = FormationList.RH_OCEAN_WAVE ; meta.toStringDiagram()
^    v    ^    v
js> m = xofy(meta, FormationList.COUPLE); undefined
1B^  1G^
2B^  2G^
3B^  3G^
4B^  4G^
js> Breather.insert(meta, m).toStringDiagram()
1B^  1G^  2Gv  2Bv  3B^  3G^  4Gv  4Bv
js> m = xofy(meta, FormationList.TANDEM); undefined
1B^

1G^
2B^

2G^
3B^

3G^
4B^

4G^
js> Breather.insert(meta, m).toStringDiagram()
1B^  2Gv  3B^  4Gv

1G^  2Bv  3G^  4Bv
js> meta = FormationList.RH_DIAMOND ; meta.toStringDiagram("|", Formation.dancerNames)
|  >
|
|
|^    v
|
|
|  <
js> m = xofy(meta, FormationList.TANDEM); undefined
1B^

1G^
2B^

2G^
3B^

3G^
4B^

4G^
js> Breather.insert(meta, m).toStringDiagram()
1G>  1B>

2B^  3Gv

2G^  3Bv

4B<  4G<

breathe

public static Formation breathe(Formation f)
Create a canonical formation by compressing the given one. This is just an invokation of breathe(List) with trivial Breather.FormationPieces consisting of a single dancer each.

Tests:
From couples back to back, step out; then breathe in:
js> importPackage(net.cscott.sdr.util) // for Fraction
js> f = FormationList.BACK_TO_BACK_COUPLES ; f.toStringDiagram()
^    ^

v    v
js> for (d in Iterator(f.dancers())) {
  >   f=f.move(d,f.location(d).forwardStep(Fraction.ONE, false));
  > }; f.toStringDiagram()
^    ^



v    v
js> Breather.breathe(f).toStringDiagram()
^    ^

v    v
From facing couples, take half a step in; breathe out:
js> importPackage(net.cscott.sdr.util) // for Fraction
js> f = FormationList.FACING_COUPLES ; f.toStringDiagram()
v    v

^    ^
js> for (d in Iterator(f.dancers())) {
  >   f=f.move(d,f.location(d).forwardStep(Fraction.ONE_HALF, false));
  > }; f.toStringDiagram()
v    v
^    ^
js> Breather.breathe(f).toStringDiagram()
v    v

^    ^
From single three quarter tag, step out; then breathe in:
js> importPackage(net.cscott.sdr.util) // for Fraction
js> f = FormationList.RH_SINGLE_THREE_QUARTER_TAG ; f.toStringDiagram()
  ^

^    v

  v
js> for (d in Iterator(f.tagged(TaggedFormation.Tag.END))) {
  >   f=f.move(d,f.location(d).forwardStep(Fraction.ONE, false));
  > }; f.toStringDiagram()
  ^


^    v


  v
js> Breather.breathe(f).toStringDiagram()
  ^

^    v

  v
From single quarter tag, take half a step in; breathe out:
js> importPackage(net.cscott.sdr.util) // for Fraction
js> f = FormationList.RH_SINGLE_QUARTER_TAG ; f.toStringDiagram()
  v

^    v

  ^
js> for (d in Iterator(f.tagged(TaggedFormation.Tag.END))) {
  >   f=f.move(d,f.location(d).forwardStep(Fraction.ONE, false));
  > }; f.toStringDiagram()
  v
^    v
  ^
js> Breather.breathe(f).toStringDiagram()
  v

^    v

  ^
From right-hand diamond, take a step and a half in; breathe out:
js> importPackage(net.cscott.sdr.util) // for Fraction
js> f = FormationList.RH_DIAMOND ; f.toStringDiagram("|", Formation.dancerNames)
|  >
|
|
|^    v
|
|
|  <
js> // XXX have to change this amount if we shrink diamonds
js> for (d in Iterator(f.tagged(TaggedFormation.Tag.POINT))) {
  >   f=f.move(d,f.location(d).sideStep(Fraction.valueOf(3,2), true));
  > }; f.toStringDiagram("|", Formation.dancerNames)
|  >
|
|^    v
|  <
js> Breather.breathe(f).toStringDiagram("|", Formation.dancerNames)
|  >
|
|^    v
|
|  <
From right-hand diamond, take 2 1/2 steps in; breathe out to stars:
js> importPackage(net.cscott.sdr.util) // for Fraction
js> f = FormationList.RH_DIAMOND ; f.toStringDiagram("|", Formation.dancerNames)
|  >
|
|
|^    v
|
|
|  <
js> // XXX have to change this amount if we shrink diamonds
js> for (d in Iterator(f.tagged(TaggedFormation.Tag.POINT))) {
  >   f=f.move(d,f.location(d).sideStep(Fraction.valueOf(5,2), true));
  > }; f.toStringDiagram("|", Formation.dancerNames)
|  >
|^ <  v
js> Breather.breathe(f).toStringDiagram("|", Formation.dancerNames)
|  >
|^    v
|  <
Facing dancers step forward; resolve collision.
js> importPackage(net.cscott.sdr.util) // for Fraction
js> f = FormationList.FACING_DANCERS ; f.toStringDiagram()
v

^
js> for (d in Iterator(f.dancers())) {
  >   f=f.move(d,f.location(d).forwardStep(Fraction.ONE, false));
  > }; f
net.cscott.sdr.calls.TaggedFormation@1db3e20[
  location={<phantom@7f>=0,0,n, <phantom@7e>=0,0,s}
  selected=[<phantom@7f>, <phantom@7e>]
  tags={<phantom@7f>=TRAILER, <phantom@7e>=TRAILER}
]
js> Breather.breathe(f).toStringDiagram()
^    v
Facing couples step forward with a left-shoulder pass; resolve collision and breathe.
js> importPackage(net.cscott.sdr.util) // for Fraction
js> f = FormationList.FACING_COUPLES ; f.toStringDiagram()
v    v

^    ^
js> for (d in Iterator(f.dancers())) {
  >   f=f.move(d,f.location(d).forwardStep(Fraction.ONE, false).addFlags(Position.Flag.PASS_LEFT));
  > }; undefined
js> Breather.breathe(f).toStringDiagram()
v    ^    v    ^

breathe

public static Formation breathe(List<Breather.FormationPiece> pieces)
Take a set of input formation pieces and substitute the given output formation pieces for them, breathing the result together so that the formation is compact. (The map giving the correspondence between dancers in the new formation and the input formations is given by the individual Breather.FormationPiece objects.) We also resolve collisions to right or left hands, depending on whether the pass-left flag is set for the Positions involved.

Tests:
Triangle point breathes to center of the base:
js> importPackage(net.cscott.sdr.util)
js> f2 = new Formation(Tools.m(
  >         Tools.p(StandardDancer.COUPLE_2_BOY, Position.getGrid(1,-1,"n")),
  >         Tools.p(StandardDancer.COUPLE_2_GIRL, Position.getGrid(3,-1,"n"))))
net.cscott.sdr.calls.Formation@94e4f4[
  location={COUPLE 2 BOY=1,-1,n, COUPLE 2 GIRL=3,-1,n}
  selected=[COUPLE 2 BOY, COUPLE 2 GIRL]
]
js> f2.toStringDiagram()
 2B^  2G^
js> fp2 = new Breather.FormationPiece(f2, FormationList.RH_MINIWAVE); undefined
js> // point on far side
js> f1 = new Formation(Tools.m(
  >         Tools.p(StandardDancer.COUPLE_1_BOY, Position.getGrid(3,1,"e"))))
net.cscott.sdr.calls.Formation@c028cc[
  location={COUPLE 1 BOY=3,1,e}
  selected=[COUPLE 1 BOY]
]
js> fp1 = new Breather.FormationPiece(f1, FormationList.SINGLE_DANCER); undefined
js> Breather.breathe(Tools.l(fp1, fp2)).toStringDiagram()
    ^

   ^    v
js> // now just slightly off-center
js> f1 = new Formation(Tools.m(
  >         Tools.p(StandardDancer.COUPLE_1_BOY, Position.getGrid(1,1,"e")
  >                                    .forwardStep(Fraction.ONE_HALF, false))))
net.cscott.sdr.calls.Formation@c028cc[
  location={COUPLE 1 BOY=1 1/2,1,e}
  selected=[COUPLE 1 BOY]
]
js> fp1 = new Breather.FormationPiece(f1, FormationList.SINGLE_DANCER); undefined
js> Breather.breathe(Tools.l(fp1, fp2)).toStringDiagram()
    ^

   ^    v
js> // point butting up against centerline
js> // NOTE doesn't float to center.  Is this correct?
js> f1 = new Formation(Tools.m(
  >         Tools.p(StandardDancer.COUPLE_1_BOY, Position.getGrid(1,1,"e"))))
net.cscott.sdr.calls.Formation@efae3b[
  location={COUPLE 1 BOY=1,1,e}
  selected=[COUPLE 1 BOY]
]
js> fp1 = new Breather.FormationPiece(f1, FormationList.SINGLE_DANCER); undefined
js> Breather.breathe(Tools.l(fp1, fp2)).toStringDiagram()
   ^

   ^    v

sdr 0.5

Copyright © 2006-2009 C. Scott Ananian