Author: Kore Nordmann Date: 2007-04-10 13:11:32 +0200 (Tue, 10 Apr 2007) New Revision: 4836
Log: - Added automatic detection of optimal rotation when using the axis rotated label renderer - Enhanced positioning of rotated lables Modified: trunk/Graph/docs/tutorial.txt trunk/Graph/src/renderer/axis_label_rotated.php trunk/Graph/tests/axis_rotated_renderer_test.php trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRender3dRotatedAxisWithLotsOfLabels.svg trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderCompleteLineChart.svg trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderCompleteLineChartReverseRotated.svg trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderRotatedAxisWithLotsOfLabels.svg trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderRotatedAxisWithLotsOfLabelsLargeAngle.svg trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderRotatedAxisWithLotsOfLabelsVertical.svg trunk/Graph/tests/renderer_3d_test.php Modified: trunk/Graph/docs/tutorial.txt =================================================================== --- trunk/Graph/docs/tutorial.txt 2007-04-09 16:57:52 UTC (rev 4835) +++ trunk/Graph/docs/tutorial.txt 2007-04-10 11:11:32 UTC (rev 4836) @@ -531,6 +531,7 @@ between two labels. This helps to recognize which bars belong together. Labels are rendered centered between two steps on the axis. + Datasets ======== Modified: trunk/Graph/src/renderer/axis_label_rotated.php =================================================================== --- trunk/Graph/src/renderer/axis_label_rotated.php 2007-04-09 16:57:52 UTC (rev 4835) +++ trunk/Graph/src/renderer/axis_label_rotated.php 2007-04-10 11:11:32 UTC (rev 4836) @@ -58,7 +58,7 @@ public function __construct( array $options = array() ) { parent::__construct( $options ); - $this->properties['angle'] = 45.; + $this->properties['angle'] = null; } /** @@ -141,6 +141,37 @@ ); } + // Determine optimal angle if none specified + if ( $this->angle === null ) + { + $minimumStepWidth = null; + foreach ( $steps as $nr => $step ) + { + if ( ( $minimumStepWidth === null ) || + ( $step->width < $minimumStepWidth ) ) + { + $minimumStepWidth = $step->width; + } + } + + $width = abs( + $axisBoundings->width * $minimumStepWidth * $this->direction->x + + $axisBoundings->height * $minimumStepWidth * $this->direction->y + ); + $height = abs( + $renderer->yAxisSpace * $this->direction->x + + $renderer->xAxisSpace * $this->direction->y + ); + + $length = sqrt( pow( $width, 2 ) + pow( $height, 2 ) ); + + printf( "Angles: %.2f, %.2f (%d * %d)\n", + $this->angle = rad2deg( asin( $width / $length ) ), + $this->angle = rad2deg( acos( $height / $length ) ), + $width, $height + ); + } + // Determine additional required axis space by boxes $firstStep = reset( $steps ); $lastStep = end( $steps ); @@ -150,7 +181,10 @@ ( $axis->position & ( ezcGraph::TOP | ezcGraph::BOTTOM ) ? deg2rad( 270 ) : deg2rad( 90 ) ); $degTextAngle = rad2deg( $textAngle ); - $this->offset = min( 1, -cos( $textAngle ) / sin( $textAngle ) ); + $this->offset = + ( $this->angle < 0 ? -1 : 1 ) * + ( $axis->position & ( ezcGraph::TOP | ezcGraph::LEFT ) ? 1 : -1 ) * + ( 1 - cos( deg2rad( $this->angle * 2 ) ) ); $axisSpaceFactor = abs( ( $this->direction->x == 0 ? 0 : @@ -230,48 +264,113 @@ } $labelSize = $labelSize * cos( deg2rad( $this->angle ) ); + $lengthReducement = min( + abs( tan( deg2rad( $this->angle ) ) * ( $labelSize / 2 ) ), + abs( $labelLength / 2 ) + ); - if ( $degTextAngle >= 90 && $degTextAngle < 270 ) + switch ( true ) { - $renderer->drawText( - new ezcGraphBoundings( - $position->x - abs( $labelLength ), - $position->y - $labelSize / 2, + case ( ( ( $degTextAngle >= 0 ) && + ( $degTextAngle < 90 ) && + ( ( $axis->position === ezcGraph::LEFT ) || + ( $axis->position === ezcGraph::RIGHT ) + ) + ) || + ( ( $degTextAngle >= 270 ) && + ( $degTextAngle < 360 ) && + ( ( $axis->position === ezcGraph::TOP ) || + ( $axis->position === ezcGraph::BOTTOM ) + ) + ) + ): + $labelBoundings = new ezcGraphBoundings( $position->x, - $position->y + $labelSize / 2 - ), - $step->label . ' ', - ezcGraph::RIGHT | ezcGraph::MIDDLE, - new ezcGraphRotation( - $degTextAngle - 180, - new ezcGraphCoordinate( - $position->x, - $position->y - ) - ) - ); - } - else - { - $renderer->drawText( - new ezcGraphBoundings( + $position->y, + $position->x + abs( $labelLength ) - $lengthReducement, + $position->y + $labelSize + ); + $labelAlignement = ezcGraph::LEFT | ezcGraph::TOP; + $labelRotation = $degTextAngle; + break; + case ( ( ( $degTextAngle >= 90 ) && + ( $degTextAngle < 180 ) && + ( ( $axis->position === ezcGraph::LEFT ) || + ( $axis->position === ezcGraph::RIGHT ) + ) + ) || + ( ( $degTextAngle >= 180 ) && + ( $degTextAngle < 270 ) && + ( ( $axis->position === ezcGraph::TOP ) || + ( $axis->position === ezcGraph::BOTTOM ) + ) + ) + ): + $labelBoundings = new ezcGraphBoundings( + $position->x - abs( $labelLength ) + $lengthReducement, + $position->y, $position->x, - $position->y - $labelSize / 2, - $position->x + abs( $labelLength ), - $position->y + $labelSize / 2 - ), - ' ' . $step->label, - ezcGraph::LEFT | ezcGraph::MIDDLE, - new ezcGraphRotation( - $degTextAngle, - new ezcGraphCoordinate( - $position->x, - $position->y - ) - ) - ); + $position->y + $labelSize + ); + $labelAlignement = ezcGraph::RIGHT | ezcGraph::TOP; + $labelRotation = $degTextAngle - 180; + break; + case ( ( ( $degTextAngle >= 180 ) && + ( $degTextAngle < 270 ) && + ( ( $axis->position === ezcGraph::LEFT ) || + ( $axis->position === ezcGraph::RIGHT ) + ) + ) || + ( ( $degTextAngle >= 90 ) && + ( $degTextAngle < 180 ) && + ( ( $axis->position === ezcGraph::TOP ) || + ( $axis->position === ezcGraph::BOTTOM ) + ) + ) + ): + $labelBoundings = new ezcGraphBoundings( + $position->x - abs( $labelLength ) + $lengthReducement, + $position->y - $labelSize, + $position->x, + $position->y + ); + $labelAlignement = ezcGraph::RIGHT | ezcGraph::BOTTOM; + $labelRotation = $degTextAngle - 180; + break; + case ( ( ( $degTextAngle >= 270 ) && + ( $degTextAngle < 360 ) && + ( ( $axis->position === ezcGraph::LEFT ) || + ( $axis->position === ezcGraph::RIGHT ) + ) + ) || + ( ( $degTextAngle >= 0 ) && + ( $degTextAngle < 90 ) && + ( ( $axis->position === ezcGraph::TOP ) || + ( $axis->position === ezcGraph::BOTTOM ) + ) + ) + ): + $labelBoundings = new ezcGraphBoundings( + $position->x, + $position->y + $labelSize, + $position->x + abs( $labelLength ) - $lengthReducement, + $position->y + ); + $labelAlignement = ezcGraph::LEFT | ezcGraph::BOTTOM; + $labelRotation = $degTextAngle; + break; } + $renderer->drawText( + $labelBoundings, + $step->label, + $labelAlignement, + new ezcGraphRotation( + $labelRotation, + $position + ) + ); + // major grid if ( $axis->majorGrid ) { Modified: trunk/Graph/tests/axis_rotated_renderer_test.php =================================================================== --- trunk/Graph/tests/axis_rotated_renderer_test.php 2007-04-09 16:57:52 UTC (rev 4835) +++ trunk/Graph/tests/axis_rotated_renderer_test.php 2007-04-10 11:11:32 UTC (rev 4836) @@ -58,6 +58,7 @@ $chart = new ezcGraphLineChart(); $chart->palette = new ezcGraphPaletteBlack(); $chart->xAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); + $chart->xAxis->axisLabelRenderer->angle = 45; $chart->yAxis->axisLabelRenderer = new ezcGraphAxisNoLabelRenderer(); $chart->data['sampleData'] = new ezcGraphArrayDataSet( array( 'sample 1' => 234, 'sample 2' => 21, 'sample 3' => 324, 'sample 4' => 120, 'sample 5' => 1) ); @@ -103,6 +104,7 @@ $chart = new ezcGraphLineChart(); $chart->palette = new ezcGraphPaletteBlack(); $chart->xAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); + $chart->xAxis->axisLabelRenderer->angle = 45; $chart->yAxis->axisLabelRenderer = new ezcGraphAxisNoLabelRenderer(); $chart->data['sampleData'] = new ezcGraphArrayDataSet( array( 'sample 1' => 234, 'sample 2' => 21, 'sample 3' => 324, 'sample 4' => 120, 'sample 5' => 1) ); @@ -148,7 +150,7 @@ $options = new ezcGraphAxisRotatedLabelRenderer(); $this->assertSame( - 45., + null, $options->angle, 'Wrong default value for property angle in class ezcGraphAxisRotatedLabelRenderer' ); @@ -190,7 +192,9 @@ $chart->xAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); $chart->xAxis->axisSpace = .25; + $chart->xAxis->axisLabelRenderer->angle = 45; $chart->yAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); + $chart->yAxis->axisLabelRenderer->angle = 45; $chart->render( 500, 200, $filename ); @@ -245,6 +249,7 @@ $chart->xAxis->labelCount = 31; $chart->xAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); + $chart->xAxis->axisLabelRenderer->angle = 45; $chart->render( 500, 200, $filename ); @@ -337,6 +342,7 @@ $chart->xAxis->labelCount = 31; $chart->xAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); + $chart->xAxis->axisLabelRenderer->angle = 45; $chart->renderer = new ezcGraphRenderer3d(); $chart->render( 500, 200, $filename ); @@ -346,6 +352,40 @@ $this->basePath . 'compare/' . __CLASS__ . '_' . __FUNCTION__ . '.svg' ); } + + public function testOptimalAngleCalculation() + { + $filename = $this->tempDir . __FUNCTION__ . '.svg'; + + $chart = new ezcGraphLineChart(); + + $chart->data['Line 1'] = new ezcGraphArrayDataSet( array( 'sample 1' => 234, 'sample 2' => 21, 'sample 3' => 324, 'sample 4' => 120, 'sample 5' => 1) ); + $chart->data['Line 2'] = new ezcGraphArrayDataSet( array( 'sample 1' => 543, 'sample 2' => 234, 'sample 3' => 298, 'sample 4' => 5, 'sample 5' => 613) ); + + $chart->xAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); + $chart->yAxis->axisLabelRenderer = new ezcGraphAxisRotatedLabelRenderer(); + + $chart->render( 500, 200, $filename ); + + $this->compare( + $filename, + $this->basePath . 'compare/' . __CLASS__ . '_' . __FUNCTION__ . '.svg' + ); + + $this->assertEqual( + $this->xAxis->axisLabelRenderer->angle, + 45., + 'Angle estimation wrong.', + 1. + ); + + $this->assertEqual( + $this->yAxis->axisLabelRenderer->angle, + 45., + 'Angle estimation wrong.', + 1. + ); + } } ?> Modified: trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRender3dRotatedAxisWithLotsOfLabels.svg =================================================================== (Binary files differ) Modified: trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderCompleteLineChart.svg =================================================================== (Binary files differ) Modified: trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderCompleteLineChartReverseRotated.svg =================================================================== (Binary files differ) Modified: trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderRotatedAxisWithLotsOfLabels.svg =================================================================== (Binary files differ) Modified: trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderRotatedAxisWithLotsOfLabelsLargeAngle.svg =================================================================== (Binary files differ) Modified: trunk/Graph/tests/data/compare/ezcGraphAxisRotatedRendererTest_testRenderRotatedAxisWithLotsOfLabelsVertical.svg =================================================================== (Binary files differ) Modified: trunk/Graph/tests/renderer_3d_test.php =================================================================== --- trunk/Graph/tests/renderer_3d_test.php 2007-04-09 16:57:52 UTC (rev 4835) +++ trunk/Graph/tests/renderer_3d_test.php 2007-04-10 11:11:32 UTC (rev 4836) @@ -1060,6 +1060,28 @@ ); } + public function testRenderBarChartWithMoreBarsThenMajorSteps() + { + $filename = $this->tempDir . __FUNCTION__ . '.svg'; + + $chart = new ezcGraphBarChart(); + $chart->legend = false; + +// $chart->xAxis = new ezcGraphChartElementNumericAxis(); +// $chart->xAxis->axisLabelRenderer = new ezcGraphAxisBoxedLabelRenderer(); + + $chart->data['dataset'] = new ezcGraphArrayDataSet( array( 12, 43, 324, 12, 43, 125, 120, 123 , 543, 12, 45, 76, 87 , 99, 834, 34, 453 ) ); + $chart->data['dataset']->color = '#3465A47F'; + + $chart->renderer = new ezcGraphRenderer3d(); + $chart->render( 500, 200, $filename ); + + $this->compare( + $filename, + $this->basePath . 'compare/' . __CLASS__ . '_' . __FUNCTION__ . '.svg' + ); + } + public function testRender3dFilledLineChartWithAxisIntersection() { $filename = $this->tempDir . __FUNCTION__ . '.svg'; -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components