diff --git a/js/curve-fitting/CurveFittingConstants.js b/js/curve-fitting/CurveFittingConstants.js index 63f72ab..c6cd188 100644 --- a/js/curve-fitting/CurveFittingConstants.js +++ b/js/curve-fitting/CurveFittingConstants.js @@ -19,9 +19,6 @@ define( function() { GRAY_COLOR: 'rgb( 107, 107, 107 )', LIGHT_GRAY_COLOR: 'rgb( 201, 201, 202 )', - // graph - PIXELS_IN_TICK: 22, - // point POINT_FILL: 'rgb( 252, 151, 64 )', POINT_RADIUS: 6, diff --git a/js/curve-fitting/model/CurveFittingModel.js b/js/curve-fitting/model/CurveFittingModel.js index b67dcbf..502f166 100644 --- a/js/curve-fitting/model/CurveFittingModel.js +++ b/js/curve-fitting/model/CurveFittingModel.js @@ -36,7 +36,13 @@ define( function( require ) { this.curve = new Curve( this.orderOfFitProperty, this.fitTypeProperty, this.maxOrderOfFit ); // graph area size - this.graphArea = new Bounds2( -10, -10, 10, 10 ); + this.graphArea = { + // x-y size for point position + size: new Bounds2( -10, -10, 10, 10 ), + + // real bounds of graph area, will be set according to available space + bounds: new Bounds2( 0, 0, 0, 0 ) + }; } return inherit( PropertySet, CurveFittingModel, { diff --git a/js/curve-fitting/view/BucketNode.js b/js/curve-fitting/view/BucketNode.js index d306f6d..58b957c 100644 --- a/js/curve-fitting/view/BucketNode.js +++ b/js/curve-fitting/view/BucketNode.js @@ -48,7 +48,7 @@ define( function( require ) { * @constructor */ function BucketNode( options ) { - Node.call( this, _.extend( {cursor: 'pointer'}, options ) ); + Node.call( this, _.extend( { cursor: 'pointer' }, options ) ); // create bucket var bucketShape = new Shape(); diff --git a/js/curve-fitting/view/ControlMenuNode.js b/js/curve-fitting/view/ControlMenuNode.js index 0d47025..104e536 100644 --- a/js/curve-fitting/view/ControlMenuNode.js +++ b/js/curve-fitting/view/ControlMenuNode.js @@ -49,7 +49,7 @@ define( function( require ) { * @constructor */ function ControlMenuNode( curveFittingModel, options ) { - VBox.call( this, _.extend( { spacing: 10 }, options ) ); + VBox.call( this, _.extend( { align: 'left', spacing: 10 }, options ) ); // create label for residual check box var residualCheckBoxLabel = new Text( ResidualsString, { font: FONT } ); diff --git a/js/curve-fitting/view/CurveFittingView.js b/js/curve-fitting/view/CurveFittingView.js index fab87ee..aea2ebe 100644 --- a/js/curve-fitting/view/CurveFittingView.js +++ b/js/curve-fitting/view/CurveFittingView.js @@ -42,6 +42,8 @@ define( function( require ) { this.addChild( controlMenuNode ); // add bucket and graph area node + var graphAreaWidth = SIM_BOUNDS.width - deviationsPanel.bounds.width - controlMenuNode.bounds.width - 50; + curveFittingModel.graphArea.bounds.setMinMax( 0, 0, graphAreaWidth, graphAreaWidth ); var bucketAndGraphAreaNode = new BucketAndGraphAreaNode( curveFittingModel ); bucketAndGraphAreaNode.centerX = bucketAndGraphAreaNode.width / 2 + PADDING_LEFT_RIGHT + 25; bucketAndGraphAreaNode.centerY = bucketAndGraphAreaNode.height / 2 + PADDING_TOP_BOTTOM; diff --git a/js/curve-fitting/view/GraphAreaNode.js b/js/curve-fitting/view/GraphAreaNode.js index 0ad44e4..8b3ca7a 100644 --- a/js/curve-fitting/view/GraphAreaNode.js +++ b/js/curve-fitting/view/GraphAreaNode.js @@ -34,50 +34,56 @@ define( function( require ) { * @param {Curve} curve model. * @param {Property.} orderOfFitProperty - Property with current order of fit. * @param {Property.} areResidualsVisibleProperty - Property to track residuals visibility. - * @param {Bounds2} plotBounds of graph area. + * @param {Object} graphAreaModel - Model of graph area. * @param {Object} [options] for graph node. * @constructor */ - function GraphAreaNode( curve, orderOfFitProperty, areResidualsVisibleProperty, plotBounds, options ) { + function GraphAreaNode( curve, orderOfFitProperty, areResidualsVisibleProperty, graphAreaModel, options ) { var self = this; - var size = new Dimension2( plotBounds.width * CurveFittingConstants.PIXELS_IN_TICK, plotBounds.height * CurveFittingConstants.PIXELS_IN_TICK ); + var graphAreaSize = graphAreaModel.size; + var graphAreaBounds = graphAreaModel.bounds; Node.call( this, options ); - this._plotBounds = plotBounds; - this._size = size; + this._graphAreaSize = graphAreaSize; + this._graphAreaBounds = graphAreaBounds; + this._graphScale = graphAreaBounds.width / graphAreaSize.width; // add white background - this.addChild( new Rectangle( 0, 0, size.width, size.height, { fill: 'white', lineWidth: 2, stroke: 'rgb( 214, 223, 226 )' } ) ); + this.addChild( new Rectangle( 0, 0, graphAreaBounds.width, graphAreaBounds.height, { + fill: 'white', + lineWidth: 2, + stroke: 'rgb( 214, 223, 226 )' + } ) ); var axisShape = new Shape(); this.addChild( new Path( axisShape, AXIS_OPTIONS ) ); // add X-axis and ticks - axisShape.moveTo( 0, size.height / 2 ); - axisShape.lineTo( size.width, size.height / 2 ); - axisShape.moveTo( AXIS_OPTIONS.lineWidth / 2, size.height / 2 - TICK_LENGTH ); - axisShape.lineTo( AXIS_OPTIONS.lineWidth / 2, size.height / 2 + TICK_LENGTH ); - axisShape.moveTo( size.width / 4, size.height / 2 - TICK_LENGTH ); - axisShape.lineTo( size.width / 4, size.height / 2 + TICK_LENGTH ); - axisShape.moveTo( 3 * size.width / 4, size.height / 2 - TICK_LENGTH ); - axisShape.lineTo( 3 * size.width / 4, size.height / 2 + TICK_LENGTH ); - axisShape.moveTo( size.width - AXIS_OPTIONS.lineWidth / 2, size.height / 2 - TICK_LENGTH ); - axisShape.lineTo( size.width - AXIS_OPTIONS.lineWidth / 2, size.height / 2 + TICK_LENGTH ); + axisShape.moveTo( 0, graphAreaBounds.height / 2 ); + axisShape.lineTo( graphAreaBounds.width, graphAreaBounds.height / 2 ); + axisShape.moveTo( AXIS_OPTIONS.lineWidth / 2, graphAreaBounds.height / 2 - TICK_LENGTH ); + axisShape.lineTo( AXIS_OPTIONS.lineWidth / 2, graphAreaBounds.height / 2 + TICK_LENGTH ); + axisShape.moveTo( graphAreaBounds.width / 4, graphAreaBounds.height / 2 - TICK_LENGTH ); + axisShape.lineTo( graphAreaBounds.width / 4, graphAreaBounds.height / 2 + TICK_LENGTH ); + axisShape.moveTo( 3 * graphAreaBounds.width / 4, graphAreaBounds.height / 2 - TICK_LENGTH ); + axisShape.lineTo( 3 * graphAreaBounds.width / 4, graphAreaBounds.height / 2 + TICK_LENGTH ); + axisShape.moveTo( graphAreaBounds.width - AXIS_OPTIONS.lineWidth / 2, graphAreaBounds.height / 2 - TICK_LENGTH ); + axisShape.lineTo( graphAreaBounds.width - AXIS_OPTIONS.lineWidth / 2, graphAreaBounds.height / 2 + TICK_LENGTH ); // add Y-axis and ticks - axisShape.moveTo( size.width / 2, 0 ); - axisShape.lineTo( size.width / 2, size.height ); - axisShape.moveTo( size.width / 2 - TICK_LENGTH, AXIS_OPTIONS.lineWidth / 2 ); - axisShape.lineTo( size.width / 2 + TICK_LENGTH, AXIS_OPTIONS.lineWidth / 2 ); - axisShape.moveTo( size.width / 2 - TICK_LENGTH, size.height / 4 ); - axisShape.lineTo( size.width / 2 + TICK_LENGTH, size.height / 4 ); - axisShape.moveTo( size.width / 2 - TICK_LENGTH, 3 * size.height / 4 ); - axisShape.lineTo( size.width / 2 + TICK_LENGTH, 3 * size.height / 4 ); - axisShape.moveTo( size.width / 2 - TICK_LENGTH, size.height - AXIS_OPTIONS.lineWidth ); - axisShape.lineTo( size.width / 2 + TICK_LENGTH, size.height - AXIS_OPTIONS.lineWidth ); + axisShape.moveTo( graphAreaBounds.width / 2, 0 ); + axisShape.lineTo( graphAreaBounds.width / 2, graphAreaBounds.height ); + axisShape.moveTo( graphAreaBounds.width / 2 - TICK_LENGTH, AXIS_OPTIONS.lineWidth / 2 ); + axisShape.lineTo( graphAreaBounds.width / 2 + TICK_LENGTH, AXIS_OPTIONS.lineWidth / 2 ); + axisShape.moveTo( graphAreaBounds.width / 2 - TICK_LENGTH, graphAreaBounds.height / 4 ); + axisShape.lineTo( graphAreaBounds.width / 2 + TICK_LENGTH, graphAreaBounds.height / 4 ); + axisShape.moveTo( graphAreaBounds.width / 2 - TICK_LENGTH, 3 * graphAreaBounds.height / 4 ); + axisShape.lineTo( graphAreaBounds.width / 2 + TICK_LENGTH, 3 * graphAreaBounds.height / 4 ); + axisShape.moveTo( graphAreaBounds.width / 2 - TICK_LENGTH, graphAreaBounds.height - AXIS_OPTIONS.lineWidth ); + axisShape.lineTo( graphAreaBounds.width / 2 + TICK_LENGTH, graphAreaBounds.height - AXIS_OPTIONS.lineWidth ); // add clip area - this.clipArea = Shape.rect( 0, 0, size.width, size.height ); + this.clipArea = Shape.rect( 0, 0, graphAreaBounds.width, graphAreaBounds.height ); var curvePath = new Path( null, { stroke: 'black', lineWidth: 2 } ); this.addChild( curvePath ); @@ -89,8 +95,8 @@ define( function( require ) { var curveShape = null; var residualsShape = null; var orderOfFit = orderOfFitProperty.value; - var xMin = self._plotBounds.minX; - var xMax = self._plotBounds.maxX; + var xMin = graphAreaSize.minX; + var xMax = graphAreaSize.maxX; var points = curve.getPoints(); var a = curve.a; var b = curve.b; @@ -169,16 +175,16 @@ define( function( require ) { var locPosition = this.globalToParentPoint( globalPosition ); return { - x: Util.toFixedNumber( this._plotBounds.minX + this._plotBounds.width * ( locPosition.x - this.bounds.minX ) / this.width, 1 ), - y: -Util.toFixedNumber( this._plotBounds.minY + this._plotBounds.height * ( locPosition.y - this.bounds.minY ) / this.height, 1 ) + x: Util.toFixedNumber( this._graphAreaSize.minX + this._graphAreaSize.width * ( locPosition.x - this.bounds.minX ) / this.width, 1 ), + y: -Util.toFixedNumber( this._graphAreaSize.minY + this._graphAreaSize.height * ( locPosition.y - this.bounds.minY ) / this.height, 1 ) }; }, // convert global coordinates to graph values getPositionFromGraphValues: function( x, y ) { return new Vector2( - (( x - this._plotBounds.minX ) / ( this._plotBounds.width )) * this._size.width, - (( -y - this._plotBounds.minY ) / ( this._plotBounds.height )) * this._size.height + (( x - this._graphAreaSize.minX ) / ( this._graphAreaSize.width )) * this._graphAreaBounds.width, + (( -y - this._graphAreaSize.minY ) / ( this._graphAreaSize.height )) * this._graphAreaBounds.height ); }, diff --git a/js/curve-fitting/view/PointNode.js b/js/curve-fitting/view/PointNode.js index 524d24e..a6a1eb9 100644 --- a/js/curve-fitting/view/PointNode.js +++ b/js/curve-fitting/view/PointNode.js @@ -80,7 +80,7 @@ define( function( require ) { drag: function( e ) { if ( isUserControlledDeltaTop ) { var y = self.globalToParentPoint( e.pointer.point ).y - clickYOffset; - pointModel.delta = Math.max( 0.1, deltaInitial - y / CurveFittingConstants.PIXELS_IN_TICK ); + pointModel.delta = Math.max( 0.1, deltaInitial - y / graphAreaNode._graphScale ); } }, end: function() { @@ -112,7 +112,7 @@ define( function( require ) { drag: function( e ) { if ( isUserControlledDeltaBottom ) { var y = self.globalToParentPoint( e.pointer.point ).y - clickYOffset; - pointModel.delta = Math.max( 0.1, deltaInitial + y / CurveFittingConstants.PIXELS_IN_TICK ); + pointModel.delta = Math.max( 0.1, deltaInitial + y / graphAreaNode._graphScale ); } }, end: function() { @@ -204,7 +204,7 @@ define( function( require ) { } ); pointModel.deltaProperty.link( function( delta ) { - var lineHeight = CurveFittingConstants.PIXELS_IN_TICK * delta; + var lineHeight = graphAreaNode._graphScale * delta; // update top error bar errorBarTop.setTranslation( 0, -lineHeight - ERROR_BAR_HEIGHT / 2 );