//(c) Copyright 2013, Scott Vorthmann.
package org.vorthmann.zome.app.impl;
import java.awt.event.ActionEvent;
import org.vorthmann.ui.Controller;
import org.vorthmann.ui.DefaultController;
import com.vzome.core.algebra.AlgebraicField;
import com.vzome.core.algebra.AlgebraicNumber;
import com.vzome.core.algebra.AlgebraicVector;
import com.vzome.core.construction.Segment;
import com.vzome.core.editor.DocumentModel;
import com.vzome.core.editor.SymmetrySystem;
import com.vzome.core.math.symmetry.Axis;
import com.vzome.core.math.symmetry.Direction;
public class PolytopesController extends DefaultController
{
private final DocumentModel model;
private String group = "H4";
private final String[] groups;
private boolean[] generateEdge = new boolean[]{ false, false, false, true };
private boolean[] renderEdge = new boolean[]{ true, true, true, true };
private AlgebraicNumber[] edgeScales = new AlgebraicNumber[4];
private final VectorController rotationQuaternion;
private final AlgebraicField field;
private final AlgebraicNumber defaultScaleFactor;
public PolytopesController( DocumentModel document )
{
this .model = document;
this .field = document .getField();
this .defaultScaleFactor = field .createPower( Direction .USER_SCALE + 2 );
for (int i = 0; i < edgeScales.length; i++)
{
edgeScales[ i ] = field .createPower( 0 );
}
// TODO: get the list from the field itself
if ( null == field .getQuaternionSymmetry( "H_4" ) ) {
groups = new String[]{ "A4", "B4/C4", "D4", "F4" };
group = "F4";
} else {
groups = new String[]{ "A4", "B4/C4", "D4", "F4", "H4" };
group = "H4";
}
rotationQuaternion = new VectorController( field .basisVector( 4, AlgebraicVector.W4 ) );
}
@Override
public void doAction( String action, ActionEvent e ) throws Exception
{
switch ( action ) {
case "setQuaternion":
/*
* The old way:
* With no symmetry axis set, the 120-cell comes out with medium blue struts.
* With a short blue symmetry axis set, it comes out with double short blue struts.
* We don't need to scale that way now, but we do need to scale in a predictable way.
* The new way:
* A quaternion value of (1,0,0,0) produces a 120-cell with medium blue struts, as before.
* With no quaternion strut selected, the quaternion value defaults to (1,0,0,0).
* With a single short blue selected as the quaternion, the quaternion is (0,1,0,0) or similar.
*/
Segment strut = model .getSelectedSegment();
if ( strut != null ) {
AlgebraicVector vector = strut .getOffset();
SymmetrySystem symm = model .getSymmetrySystem();
Axis zone = symm .getAxis( vector );
AlgebraicNumber len = zone .getLength( vector );
len = zone .getOrbit() .getLengthInUnits( len );
vector = zone .normal() .scale( len );
rotationQuaternion .setVector( vector .inflateTo4d() );
} else {
AlgebraicVector vector = this .field .basisVector( 4, AlgebraicVector.W4 );
rotationQuaternion .setVector( vector );
}
return;
default:
break;
}
if ( "generate".equals( action ) )
{
int index = 0;
int edgesToRender = 0;
for ( int i = 0; i < 4; i++ )
{
if ( generateEdge [ i ] )
index += 1 << i;
if ( renderEdge[ i ] )
edgesToRender += 1 << i;
}
AlgebraicVector quaternion = rotationQuaternion .getVector() .scale( this .defaultScaleFactor );
model .generatePolytope( group, group, index, edgesToRender, quaternion, edgeScales );
}
else if ( action .startsWith( "setGroup." ) )
{
group = action .substring( "setGroup." .length() );
}
else if ( action .startsWith( "edge." ) )
{
String edgeName = action .substring( "edge." .length() );
int edge = Integer .parseInt( edgeName );
boolean state = generateEdge[ edge ];
generateEdge[ edge ] = ! state;
}
else if ( action .startsWith( "render." ) )
{
String edgeName = action .substring( "render." .length() );
int edge = Integer .parseInt( edgeName );
boolean state = renderEdge[ edge ];
renderEdge[ edge ] = ! state;
}
else
super.doAction( action, e );
}
@Override
public String[] getCommandList( String listName )
{
return this .groups;
}
@Override
public String getProperty( String propName )
{
if ( "group" .equals( propName ) )
{
return this .group;
}
else if ( propName .startsWith( "edge." ) )
{
String edgeName = propName .substring( "edge." .length() );
int edge = Integer .parseInt( edgeName );
return Boolean .toString( generateEdge[ edge ] );
}
else if ( propName .startsWith( "render." ) )
{
String edgeName = propName .substring( "render." .length() );
int edge = Integer .parseInt( edgeName );
return Boolean .toString( renderEdge[ edge ] );
}
else
return super .getProperty( propName );
}
@Override
public Controller getSubController( String name )
{
switch ( name ) {
case "rotation":
return this .rotationQuaternion;
default:
return super.getSubController( name );
}
}
}