Skip to content

Commit

Permalink
tweaked the spiral placement algorithm until it look reasonably good,…
Browse files Browse the repository at this point in the history
… see #191
  • Loading branch information
jbphet committed Feb 8, 2019
1 parent 6e4679f commit 4c91765
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 22 deletions.
57 changes: 36 additions & 21 deletions js/common/model/EnergyChunkDistributor.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ define( function( require ) {
var ENERGY_CHUNK_CROSS_SECTIONAL_AREA = Math.PI * Math.pow( ENERGY_CHUNK_DIAMETER, 2 );
var DRAG_COEFFICIENT = 500; // unitless, empirically chosen

// width of an energy chunk in the view, used to keep them in bounds
var ENERGY_CHUNK_VIEW_TO_MODEL_WIDTH = 0.012;

// Thresholds for deciding whether or not to perform redistribution. These value should be chosen such that particles
// spread out, then stop all movement.
var REDISTRIBUTION_THRESHOLD_ENERGY = 1E-7; // in joules (I think)
Expand Down Expand Up @@ -415,42 +418,54 @@ define( function( require ) {
var sliceBounds = slices[ sliceIndex ].bounds;
var sliceCenter = sliceBounds.getCenter();
var numEnergyChunksInSlice = slices[ sliceIndex ].energyChunkList.length;
// var numTurns = 2.25 + ( numEnergyChunksInSlice / 8 ); // empirically determined by trial and error
var numTurns = 2;
var numTurns = 2.7 + ( numEnergyChunksInSlice / 9 ); // empirically determined by trial and error
var maxAngle = numTurns * Math.PI * 2;
var multiplier = 1 / maxAngle;

// in each slice, orient the spiral slightly differently to make things look more random
var spiralOffsetAngle = sliceIndex * ( 2 * Math.PI / slices.length );
// define the variables that will be used to iterate through the spiral in the loop below
var angleIncrement = ( maxAngle / ( numEnergyChunksInSlice + 1 ) ) / 2;
var startAngle = maxAngle / 2 + angleIncrement;

// define the variables that will be used to choose the angles in the spiral in the loop below
// var initialAngle = maxAngle / 3;
// var angleRange = maxAngle - initialAngle;
// var angleIncrement = angleRange / ( numEnergyChunksInSlice + 1 );
// experiment where everything is at max angle
var initialAngle = maxAngle;
// var angleRange = maxAngle - initialAngle;
var angleIncrement = 0;
// Define a value that will be used to offset the spiral rotation so that things are less likely to line up
// across slices.
var spiralAngleOffsetPerSlice = ( 2 * Math.PI ) / slices.length;

// loop through each energy chunk in this slice, setting its position using an equation for a spiral
for ( var ecIndex = 0; ecIndex < numEnergyChunksInSlice; ecIndex++ ) {

var ec = slices[ sliceIndex ].energyChunkList.get( ecIndex );
var angle = initialAngle + ecIndex * angleIncrement;

// wind in opposite directions in every other slice to make things look more rangom
// calculate the angle to feed into the formula
var angle = startAngle + ecIndex * angleIncrement;

// calculate a radius value within the "normalized spiral", where the radius is 1 at the max angle
var normalizedRadius = multiplier * Math.abs( angle );
assert && assert( normalizedRadius <= 1, 'normalized length must be 1 or smaller' );

// calculate an angle the is rotated a bit based on the spiral offset
var adjustedAngle = angle + sliceIndex * spiralAngleOffsetPerSlice;

// Determine the max possible radius for the current angle, which is bassicall the distance to the closest
// edge. This must be reduced a bit to account for the fact that energy chunks have some width in the view.
var maxRadius = getCenterToEdgeDistance( sliceBounds, adjustedAngle ) - ENERGY_CHUNK_VIEW_TO_MODEL_WIDTH / 2;

// determine the radius to use as a function of the value from the normalized spiral and the max value
var radius = maxRadius * normalizedRadius;

// reverse the radius on every other slice to get more spread between slices
if ( sliceIndex % 2 === 1 ) {
angle = -angle;
radius = -radius;
adjustedAngle = -adjustedAngle;
}
var normalizedLength = multiplier * ( Math.abs( angle ) - spiralOffsetAngle );
assert && assert( normalizedLength <= 1, 'normalized length must be 1 or smaller' );
var maxLength = getCenterToEdgeDistance( sliceBounds, angle ) * 0.95; // reduced a little so EC nodes stay inside
var length = maxLength * normalizedLength;

// calculate the destination using polar coordinates
var ecDestination = new Vector2();
ecDestination.setPolar( length, angle );
ecDestination.setPolar( radius, adjustedAngle );
ecDestination.add( sliceCenter );

// animate the energy chunk towards its destination if it isn't there already
if ( !ec.positionProperty.value.equals( ecDestination ) ) {
moveECTowardsDestination( slices[ sliceIndex ].energyChunkList.get( ecIndex ), ecDestination, dt );
moveECTowardsDestination( ec, ecDestination, dt );
ecMoved = true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion js/intro/model/RectangularThermalMovableModelElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ define( function( require ) {
var targetNumECs = EFACConstants.ENERGY_TO_NUM_CHUNKS_MAPPER( this.energy );

// start with the middle slice and cycle through in order, added chunks evenly to each
var slideIndex = Math.floor( this.slices.length / 2 );
var slideIndex = Math.floor( this.slices.length / 2 ) - 1;
var numECsAdded = 0;
while ( numECsAdded < targetNumECs ) {
var slice = this.slices[ slideIndex ];
Expand Down

0 comments on commit 4c91765

Please sign in to comment.