001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030/** 031 * 032 */ 033package org.openimaj.vis.general; 034import org.openimaj.image.DisplayUtilities; 035import org.openimaj.image.Image; 036import org.openimaj.image.MBFImage; 037import org.openimaj.image.colour.RGBColour; 038import org.openimaj.math.geometry.point.Point2d; 039import org.openimaj.math.geometry.point.Point2dImpl; 040import org.openimaj.math.geometry.transforms.TransformUtilities; 041import org.openimaj.vis.DataUnitsTransformer; 042 043import Jama.Matrix; 044 045/** 046 * TODO: javadoc 047 * 048 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 049 * @param <Q> The pixel type of the image you'll be drawing the axes to 050 * @param <I> The type of image being drawn to 051 * @created 3 Jun 2013 052 */ 053public class AxesRenderer2D<Q,I extends Image<Q,I>> 054 implements DataUnitsTransformer<Q,double[],int[]> 055{ 056 /** The axis renderer we'll use to render the x axis */ 057 private final AxisRenderer2D<Q> xAxisRenderer = new AxisRenderer2D<Q>(); 058 059 /** The axis renderer we'll use to render the y axis */ 060 private final AxisRenderer2D<Q> yAxisRenderer = new AxisRenderer2D<Q>(); 061 062 /** The configuration for the xAxis */ 063 private AxisConfig<Q> xAxisConfig = this.xAxisRenderer.getConfig(); 064 065 /** The configuration for the yAxis */ 066 private AxisConfig<Q> yAxisConfig = this.yAxisRenderer.getConfig(); 067 068 /** How far from the left of the image will the x axis start */ 069 private int axisPaddingLeft = 20; 070 071 /** How far from the right of the image will the x axis stop */ 072 private int axisPaddingRight = 20; 073 074 /** How far from the top of the image with the y axis start */ 075 private int axisPaddingTop = 20; 076 077 /** How far from the bottom of the image will the y axis stop */ 078 private int axisPaddingBottom = 20; 079 080 /** Whether to work out the ideal position for the axes */ 081 private boolean autoScaleAxes = false; 082 083 private Matrix dataTransformMatrix; 084 085 /** 086 * Default constructor 087 */ 088 public AxesRenderer2D() 089 { 090 this.xAxisConfig.setOrientation( new double[] { 0 } ); 091 this.yAxisConfig.setOrientation( new double[] { 092 this.xAxisConfig.getOrientation()[0]-Math.PI/2d } ); 093 } 094 095 /** 096 * Set the orientation of the x axis 097 * @param rads angle in radians 098 */ 099 public void setOrientation( final double rads ) 100 { 101 this.xAxisConfig.setOrientation( new double[] { rads } ); 102 this.yAxisConfig.setOrientation( new double[] { 103 this.xAxisConfig.getOrientation()[0]-Math.PI/2d } ); 104 105 } 106 107 /** 108 * Render the axis to the given image 109 * @param image The image to draw the axes to 110 */ 111 public void renderAxis( final I image ) 112 { 113 // Set the image to draw upon 114 this.setImage( image ); 115 116 this.xAxisRenderer.renderAxis(); 117 this.yAxisRenderer.renderAxis(); 118 119// 120// // Create the renderer to draw to the image 121// final ImageRenderer<Q, ? extends Image<Q, I>> ir = image.createRenderer( RenderHints.ANTI_ALIASED ); 122// 123// // Get the dimensions of the image to draw to 124// final int w = image.getWidth(); 125// final int h = image.getHeight(); 126// 127// // Find the pixel spacing to use 128// final double xRange = this.maxXValue - this.minXValue; 129// this.xUnitSizePx = (w-this.axisPaddingLeft-this.axisPaddingRight) / xRange; 130// final double yRange = this.maxYValue - this.minYValue; 131// this.yUnitSizePx = (h-this.axisPaddingBottom-this.axisPaddingTop) / yRange; 132// 133// // Pixel position of where the axes crossing happens 134// this.yAxisConfig.setLocation( new double[] {this.axisPaddingLeft - this.minXValue*this.xUnitSizePx,0} ); 135// this.xAxisPosition = h - this.axisPaddingBottom + this.minYValue*this.yUnitSizePx; 136// 137// // Draw the x-axis minor ticks 138// if( this.drawXAxis && this.drawXTicks ) 139// { 140// for( double v = this.minXValue; v <= this.maxXValue; v += this.xMinorTickSpacing ) 141// { 142// if( this.drawMinorTickGrid ) 143// ir.drawLine( 144// (int)(this.yAxisConfig.getLocation()[0] + v * this.xUnitSizePx), 145// 0, 146// (int)(this.yAxisConfig.getLocation()[0] + v * this.xUnitSizePx), 147// image.getHeight(), 148// this.minorGridThickness, 149// this.minorGridColour ); 150// 151// ir.drawLine( 152// (int)(this.yAxisConfig.getLocation()[0] + v * this.xUnitSizePx), 153// (int)(this.xAxisPosition-this.minorTickLength), 154// (int)(this.yAxisConfig.getLocation()[0] + v * this.xUnitSizePx), 155// (int)(this.xAxisPosition+this.minorTickLength), 156// this.minorTickThickness, 157// this.minorTickColour ); 158// } 159// } 160// 161// // Draw the x-axis major ticks 162// if( this.drawXAxis && this.drawXTicks ) 163// { 164// for( double v = this.minXValue; v <= this.maxXValue; v += this.xMajorTickSpacing ) 165// { 166// if( this.drawMajorTickGrid ) 167// ir.drawLine( 168// (int)(this.yAxisConfig.getLocation()[0] + v * this.xUnitSizePx), 169// 0, 170// (int)(this.yAxisConfig.getLocation()[0] + v * this.xUnitSizePx), 171// image.getHeight(), 172// this.majorGridThickness, 173// this.majorGridColour ); 174// 175// ir.drawLine( 176// (int)(this.yAxisConfig.getLocation()[0] + v * this.xUnitSizePx), 177// (int)(this.xAxisPosition-this.majorTickLength), 178// (int)(this.yAxisConfig.getLocation()[0] + v * this.xUnitSizePx), 179// (int)(this.xAxisPosition+this.majorTickLength), 180// this.majorTickThickness, 181// this.majorTickColour ); 182// } 183// } 184// 185// // Draw the x tick labels 186// double maxXLabelPosition = 0; 187// if( this.drawXAxis && this.drawXTickLabels ) 188// { 189// final int yPos = (int)(this.xAxisPosition + this.xTickLabelSize + this.majorTickLength 190// + this.xTickLabelSize/2 ); 191// 192// @SuppressWarnings( "rawtypes" ) 193// final FontStyle s = this.xTickLabelFont.createStyle( ir ); 194// s.setFontSize( this.xTickLabelSize ); 195// 196// @SuppressWarnings( "rawtypes" ) 197// final FontRenderer r = this.xTickLabelFont.getRenderer( ir ); 198// 199// for( double v = this.minXValue; v <= this.maxXValue; v += this.xLabelSpacing ) 200// { 201// String text = ""+v; 202// if( this.xAxisLabelTransformer != null ) 203// text = this.xAxisLabelTransformer.transform( v ); 204// 205// final float fw = r.getBounds( text, s ).width; 206// final int xPos = (int)(this.yAxisConfig.getLocation()[0] + v*this.xUnitSizePx - fw/2); 207// ir.drawText( text, xPos, yPos, this.xTickLabelFont, 208// this.xTickLabelSize, this.xTickLabelColour ); 209// } 210// maxXLabelPosition = yPos; 211// } 212// 213// // Draw the y-axis ticks 214// if( this.drawYAxis && this.drawYTicks ) 215// { 216// for( double v = this.minYValue; v <= this.maxYValue; v += this.yMinorTickSpacing ) 217// { 218// if( this.drawMinorTickGrid ) 219// ir.drawLine( 220// 0, 221// (int)(this.xAxisPosition - v * this.yUnitSizePx), 222// image.getWidth(), 223// (int)(this.xAxisPosition - v * this.yUnitSizePx), 224// this.minorGridThickness, 225// this.minorGridColour ); 226// 227// ir.drawLine( 228// (int)(this.yAxisConfig.getLocation()[0]-this.minorTickLength), 229// (int)(this.xAxisPosition - v * this.yUnitSizePx), 230// (int)(this.yAxisConfig.getLocation()[0]+this.minorTickLength), 231// (int)(this.xAxisPosition - v * this.yUnitSizePx), 232// this.minorTickThickness, 233// this.minorTickColour ); 234// } 235// } 236// 237// // Draw the y-axis ticks 238// if( this.drawYAxis && this.drawYTicks ) 239// { 240// for( double v = this.minYValue; v <= this.maxYValue; v += this.yMajorTickSpacing ) 241// { 242// if( this.drawMajorTickGrid ) 243// ir.drawLine( 244// 0, 245// (int)(this.xAxisPosition - v * this.yUnitSizePx), 246// image.getWidth(), 247// (int)(this.xAxisPosition - v * this.yUnitSizePx), 248// this.majorGridThickness, 249// this.majorGridColour ); 250// 251// ir.drawLine( 252// (int)(this.yAxisPosition-this.majorTickLength), 253// (int)(this.xAxisPosition - v * this.yUnitSizePx), 254// (int)(this.yAxisPosition+this.majorTickLength), 255// (int)(this.xAxisPosition - v * this.yUnitSizePx), 256// this.majorTickThickness, 257// this.majorTickColour ); 258// } 259// } 260// 261// // Draw the x tick labels 262// double minYLabelPosition = this.yAxisPosition; 263// if( this.drawYAxis && this.drawYTickLabels ) 264// { 265// @SuppressWarnings( "rawtypes" ) 266// final FontStyle s = this.yTickLabelFont.createStyle( ir ); 267// s.setFontSize( this.yTickLabelSize ); 268// 269// @SuppressWarnings( "rawtypes" ) 270// final FontRenderer r = this.yTickLabelFont.getRenderer( ir ); 271// 272// for( double v = this.minYValue; v <= this.maxYValue; v += this.yLabelSpacing ) 273// { 274// String text = ""+v; 275// if( this.yAxisLabelTransformer != null ) 276// text = this.yAxisLabelTransformer.transform( v ); 277// 278// final float fw = r.getBounds( text, s ).width; 279// final int xPos = (int)(this.yAxisPosition - fw - this.majorTickLength 280// - this.yTickLabelSize/2 ); // Last part is just a bit of padding 281// final int yPos = (int)(this.xAxisPosition - v*this.yUnitSizePx + this.yTickLabelSize/2 ); 282// ir.drawText( text, xPos, yPos, this.yTickLabelFont, 283// this.yTickLabelSize, this.yTickLabelColour ); 284// minYLabelPosition = Math.min( xPos, minYLabelPosition ); 285// } 286// } 287// 288// // Draw the X-axis 289// if( this.drawXAxis ) 290// ir.drawLine( this.axisPaddingLeft, (int)this.xAxisPosition, w-this.axisPaddingRight, 291// (int)this.xAxisPosition, this.xAxisThickness, this.xAxisColour ); 292// 293// // Draw the Y-axis 294// if( this.drawYAxis ) 295// ir.drawLine( (int)this.yAxisPosition, this.axisPaddingTop, (int)this.yAxisPosition, 296// h-this.axisPaddingBottom, this.yAxisThickness, this.yAxisColour ); 297// 298// // Draw the X-axis label 299// if( this.drawXAxis && this.drawXAxisName ) 300// ir.drawText( this.xAxisName, this.axisPaddingLeft, 301// (int)(maxXLabelPosition + this.xAxisNameSize), 302// this.xAxisNameFont, 303// this.xAxisNameSize, this.xAxisNameColour ); 304// 305// // Draw the Y-axis label 306// if( this.drawYAxis && this.drawYAxisName ) 307// { 308// @SuppressWarnings( "rawtypes" ) 309// final FontStyle s = this.yAxisNameFont.createStyle( ir ); 310// s.setFontSize( this.yAxisNameSize ); 311// 312// final float fw = this.yAxisNameFont.getRenderer( ir ).getBounds( 313// this.yAxisName, s ).width; 314// 315// ir.drawText( this.yAxisName, (int)(minYLabelPosition - fw), 316// this.yAxisNameSize + this.axisPaddingTop, this.yAxisNameFont, 317// this.yAxisNameSize, this.yAxisNameColour ); 318// } 319 } 320 321 /** 322 * For a given coordinate in the units of the data, will calculate 323 * the pixel position. 324 * 325 * @param image The image in which the axes were drawn 326 * @param x The x position 327 * @param y The y position 328 * @return The pixel position 329 */ 330// @Override 331// public Point2d calculatePosition( 332// final I image, final double x, final double y ) 333// { 334// return new Point2dImpl( (float)(this.yAxisPosition + x*this.xUnitSizePx), 335// (float)(this.xAxisPosition - y*this.yUnitSizePx) ); 336// } 337 338 /** 339 * @param drawXAxis the drawXAxis to set 340 */ 341 public void setDrawXAxis( final boolean drawXAxis ) 342 { 343 this.xAxisConfig.getRenderingConfig().setRenderAxis( drawXAxis ); 344 } 345 346 /** 347 * @param drawYAxis the drawYAxis to set 348 */ 349 public void setDrawYAxis( final boolean drawYAxis ) 350 { 351 this.yAxisConfig.getRenderingConfig().setRenderAxis( drawYAxis ); 352 } 353 354 /** 355 * @return the axisPaddingLeft 356 */ 357 public int getAxisPaddingLeft() 358 { 359 return this.axisPaddingLeft; 360 } 361 362 /** 363 * @param axisPaddingLeft the axisPaddingLeft to set 364 */ 365 public void setAxisPaddingLeft( final int axisPaddingLeft ) 366 { 367 this.axisPaddingLeft = axisPaddingLeft; 368 } 369 370 /** 371 * @return the axisPaddingRight 372 */ 373 public int getAxisPaddingRight() 374 { 375 return this.axisPaddingRight; 376 } 377 378 /** 379 * @param axisPaddingRight the axisPaddingRight to set 380 */ 381 public void setAxisPaddingRight( final int axisPaddingRight ) 382 { 383 this.axisPaddingRight = axisPaddingRight; 384 } 385 386 /** 387 * @return the axisPaddingTop 388 */ 389 public int getAxisPaddingTop() 390 { 391 return this.axisPaddingTop; 392 } 393 394 /** 395 * @param axisPaddingTop the axisPaddingTop to set 396 */ 397 public void setAxisPaddingTop( final int axisPaddingTop ) 398 { 399 this.axisPaddingTop = axisPaddingTop; 400 } 401 402 /** 403 * @return the axisPaddingBottom 404 */ 405 public int getAxisPaddingBottom() 406 { 407 return this.axisPaddingBottom; 408 } 409 410 /** 411 * @param axisPaddingBottom the axisPaddingBottom to set 412 */ 413 public void setAxisPaddingBottom( final int axisPaddingBottom ) 414 { 415 this.axisPaddingBottom = axisPaddingBottom; 416 } 417 418 /** 419 * @param xAxisPosition the xAxisPosition to set 420 */ 421 public void setxAxisPosition( final double xAxisPosition ) 422 { 423 this.xAxisConfig.setLocation( new double[] { this.axisPaddingLeft, xAxisPosition } ); 424 } 425 426 /** 427 * The y position of the x axis. 428 * @return the y position. 429 */ 430 public double getxAxisPosition() 431 { 432 return this.xAxisConfig.getLocation()[1]; 433 } 434 435 /** 436 * @return the autoScaleAxes 437 */ 438 public boolean isAutoScaleAxes() 439 { 440 return this.autoScaleAxes; 441 } 442 443 /** 444 * @param autoScaleAxes the autoScaleAxes to set 445 */ 446 public void setAutoScaleAxes( final boolean autoScaleAxes ) 447 { 448 this.autoScaleAxes = autoScaleAxes; 449 } 450 451 /** 452 * @param xAxisThickness the xAxisThickness to set 453 */ 454 public void setxAxisThickness( final int xAxisThickness ) 455 { 456 this.xAxisConfig.getRenderingConfig().setThickness( xAxisThickness ); 457 } 458 459 /** 460 * @param xAxisColour the xAxisColour to set 461 */ 462 public void setxAxisColour( final Q xAxisColour ) 463 { 464 this.xAxisConfig.getRenderingConfig().setColour( xAxisColour ); 465 } 466 467 /** 468 * @param yAxisThickness the yAxisThickness to set 469 */ 470 public void setyAxisThickness( final int yAxisThickness ) 471 { 472 this.yAxisConfig.getRenderingConfig().setThickness( yAxisThickness ); 473 } 474 475 /** 476 * @param yAxisColour the yAxisColour to set 477 */ 478 public void setyAxisColour( final Q yAxisColour ) 479 { 480 this.yAxisConfig.getRenderingConfig().setColour( yAxisColour ); 481 } 482 483 /** 484 * @param maxXValue the maxXValue to set 485 */ 486 public void setMaxXValue( final double maxXValue ) 487 { 488 this.xAxisConfig.setMaxValue( this.xAxisRenderer.nearestHigherMajorTick( maxXValue ) ); 489 } 490 491 /** 492 * @param minXValue the minXValue to set 493 */ 494 public void setMinXValue( final double minXValue ) 495 { 496 this.xAxisConfig.setMinValue( this.xAxisRenderer.nearestLowerMajorTick( minXValue ) ); 497 } 498 499 /** 500 * @param maxYValue the maxYValue to set 501 */ 502 public void setMaxYValue( final double maxYValue ) 503 { 504 this.yAxisConfig.setMaxValue( this.yAxisRenderer.nearestHigherMajorTick( maxYValue ) ); 505 } 506 507 /** 508 * Returns the maximum value of the y axis 509 * @return The y axis maximum value 510 */ 511 public double getMaxYValue() 512 { 513 return this.yAxisConfig.getMaxValue(); 514 } 515 516 /** 517 * @param minYValue the minYValue to set 518 */ 519 public void setMinYValue( final double minYValue ) 520 { 521 this.yAxisConfig.setMinValue( this.yAxisRenderer.nearestLowerMajorTick( minYValue ) ); 522 } 523 524 /** 525 * @param xMinorTickSpacing the xMinorTickSpacing to set 526 */ 527 public void setxMinorTickSpacing( final double xMinorTickSpacing ) 528 { 529 this.xAxisConfig.getRenderingConfig().setMinorTickSpacing( xMinorTickSpacing ); 530 } 531 532 /** 533 * @param yMinorTickSpacing the yMinorTickSpacing to set 534 */ 535 public void setyMinorTickSpacing( final double yMinorTickSpacing ) 536 { 537 this.yAxisConfig.getRenderingConfig().setMinorTickSpacing( yMinorTickSpacing ); 538 } 539 540 /** 541 * @param xMajorTickSpacing the xMajorTickSpacing to set 542 */ 543 public void setxMajorTickSpacing( final double xMajorTickSpacing ) 544 { 545 this.xAxisConfig.getRenderingConfig().setMajorTickSpacing( xMajorTickSpacing ); 546 } 547 548 /** 549 * @param yMajorTickSpacing the yMajorTickSpacing to set 550 */ 551 public void setyMajorTickSpacing( final double yMajorTickSpacing ) 552 { 553 this.yAxisConfig.getRenderingConfig().setMajorTickSpacing( yMajorTickSpacing ); 554 } 555 556 /** 557 * @param minorTickLength the minorTickLength to set 558 */ 559 public void setMinorTickLength( final int minorTickLength ) 560 { 561 this.yAxisConfig.getRenderingConfig().setMinorTickLength( minorTickLength ); 562 this.xAxisConfig.getRenderingConfig().setMinorTickLength( minorTickLength ); 563 } 564 565 /** 566 * @param majorTickLength the majorTickLength to set 567 */ 568 public void setMajorTickLength( final int majorTickLength ) 569 { 570 this.yAxisConfig.getRenderingConfig().setMajorTickLength( majorTickLength ); 571 this.xAxisConfig.getRenderingConfig().setMajorTickLength( majorTickLength ); 572 } 573 574 /** 575 * @param minorTickColour the minorTickColour to set 576 */ 577 public void setMinorTickColour( final Q minorTickColour ) 578 { 579 this.yAxisConfig.getRenderingConfig().setMinorTickColour( minorTickColour ); 580 this.xAxisConfig.getRenderingConfig().setMinorTickColour( minorTickColour ); 581 } 582 583 /** 584 * @param majorTickColour the majorTickColour to set 585 */ 586 public void setMajorTickColour( final Q majorTickColour ) 587 { 588 this.yAxisConfig.getRenderingConfig().setMajorTickColour( majorTickColour ); 589 this.xAxisConfig.getRenderingConfig().setMajorTickColour( majorTickColour ); 590 } 591 592 /** 593 * @param majorTickThickness the majorTickThickness to set 594 */ 595 public void setMajorTickThickness( final int majorTickThickness ) 596 { 597 this.yAxisConfig.getRenderingConfig().setMajorTickThickness( majorTickThickness ); 598 this.xAxisConfig.getRenderingConfig().setMajorTickThickness( majorTickThickness ); 599 } 600 601 /** 602 * @param minorTickThickness the minorTickThickenss to set 603 */ 604 public void setMinorTickThickenss( final int minorTickThickness ) 605 { 606 this.yAxisConfig.getRenderingConfig().setMinorTickThickness( minorTickThickness ); 607 this.xAxisConfig.getRenderingConfig().setMinorTickThickness( minorTickThickness ); 608 } 609 610 /** 611 * @param drawXTickLabels the drawXTickLabels to set 612 */ 613 public void setDrawXTickLabels( final boolean drawXTickLabels ) 614 { 615 this.xAxisConfig.getRenderingConfig().setDrawMajorTickLabels( drawXTickLabels ); 616 this.xAxisConfig.getRenderingConfig().setDrawMinorTickLabels( drawXTickLabels ); 617 } 618 619 /** 620 * @param drawYTickLabels the drawYTickLabels to set 621 */ 622 public void setDrawYTickLabels( final boolean drawYTickLabels ) 623 { 624 this.yAxisConfig.getRenderingConfig().setDrawMajorTickLabels( drawYTickLabels ); 625 this.yAxisConfig.getRenderingConfig().setDrawMinorTickLabels( drawYTickLabels ); 626 } 627 628 /** 629 * @param xTickLabelSize the xTickLabelSize to set 630 */ 631 public void setxTickLabelSize( final int xTickLabelSize ) 632 { 633// this.xTickLabelSize = xTickLabelSize; 634 // TODO: 635 } 636 637 /** 638 * @param xTickLabelColour the xTickLabelColour to set 639 */ 640 public void setxTickLabelColour( final Q xTickLabelColour ) 641 { 642// this.xTickLabelColour = xTickLabelColour; 643 // TODO: 644 } 645 646 /** 647 * @param yTickLabelSize the yTickLabelSize to set 648 */ 649 public void setyTickLabelSize( final int yTickLabelSize ) 650 { 651// yAxisConfig.getRenderingConfig().setMajorTickLabelFont( majorTickLabelFont ); 652 // TODO: 653 } 654 655 /** 656 * @param yTickLabelColour the yTickLabelColour to set 657 */ 658 public void setyTickLabelColour( final Q yTickLabelColour ) 659 { 660// this.yTickLabelColour = yTickLabelColour; 661// yAxisConfig.getRenderingConfig().getMajor 662 // TODO: 663 } 664 665 /** 666 * @param autoSpaceLabels the autoSpaceLabels to set 667 */ 668 public void setAutoSpaceLabels( final boolean autoSpaceLabels ) 669 { 670// this.autoSpaceLabels = autoSpaceLabels; 671 // TODO: 672 } 673 674 /** 675 * @param autoSpaceTicks the autoSpaceTicks to set 676 */ 677 public void setAutoSpaceTicks( final boolean autoSpaceTicks ) 678 { 679// this.autoSpaceTicks = autoSpaceTicks; 680 // TODO: 681 } 682 683 /** 684 * @param minTickSpacing the minTickSpacing to set 685 */ 686 public void setMinTickSpacing( final int minTickSpacing ) 687 { 688 // TODO: 689 } 690 691 /** 692 * @param xLabelSpacing the xLabelSpacing to set 693 */ 694 public void setxLabelSpacing( final double xLabelSpacing ) 695 { 696// xAxisConfig.getRenderingConfig().setMajor 697 // TODO: 698 } 699 700 /** 701 * @param yLabelSpacing the yLabelSpacing to set 702 */ 703 public void setyLabelSpacing( final double yLabelSpacing ) 704 { 705// this.yLabelSpacing = yLabelSpacing; 706 // TODO: 707 } 708 709 /** 710 * @param xAxisName the xAxisName to set 711 */ 712 public void setxAxisName( final String xAxisName ) 713 { 714 this.xAxisConfig.setName( xAxisName ); 715 } 716 717 /** 718 * @param yAxisName the yAxisName to set 719 */ 720 public void setyAxisName( final String yAxisName ) 721 { 722 this.yAxisConfig.setName( yAxisName ); 723 } 724 725 /** 726 * @param drawYAxisName the drawYAxisName to set 727 */ 728 public void setDrawYAxisName( final boolean drawYAxisName ) 729 { 730// this.drawYAxisName = drawYAxisName; 731 // TODO: 732 } 733 734 /** 735 * @param drawXAxisName the drawXAxisName to set 736 */ 737 public void setDrawXAxisName( final boolean drawXAxisName ) 738 { 739 // xAxisConfig.getRenderingConfig() 740 // TODO: 741 } 742 743 /** 744 * @param xAxisNameSize the xAxisNameSize to set 745 */ 746 public void setxAxisNameSize( final int xAxisNameSize ) 747 { 748 this.xAxisConfig.getRenderingConfig().setNameSize( xAxisNameSize ); 749 } 750 751 /** 752 * @param xAxisNameColour the xAxisNameColour to set 753 */ 754 public void setxAxisNameColour( final Q xAxisNameColour ) 755 { 756 this.xAxisConfig.getRenderingConfig().setNameColour( xAxisNameColour ); 757 } 758 759 /** 760 * @param yAxisNameSize the yAxisNameSize to set 761 */ 762 public void setyAxisNameSize( final int yAxisNameSize ) 763 { 764 this.yAxisConfig.getRenderingConfig().setNameSize( yAxisNameSize ); 765 } 766 767 /** 768 * @param yAxisNameColour the yAxisNameColour to set 769 */ 770 public void setyAxisNameColour( final Q yAxisNameColour ) 771 { 772 this.yAxisConfig.getRenderingConfig().setNameColour( yAxisNameColour ); 773 } 774 775 /** 776 * @param drawXTicks the drawXTicks to set 777 */ 778 public void setDrawXTicks( final boolean drawXTicks ) 779 { 780 this.xAxisConfig.getRenderingConfig().setDrawMajorTicks( drawXTicks ); 781 this.xAxisConfig.getRenderingConfig().setDrawMinorTicks( drawXTicks ); 782 } 783 784 /** 785 * @param drawYTicks the drawYTicks to set 786 */ 787 public void setDrawYTicks( final boolean drawYTicks ) 788 { 789 this.yAxisConfig.getRenderingConfig().setDrawMajorTicks( drawYTicks ); 790 this.yAxisConfig.getRenderingConfig().setDrawMinorTicks( drawYTicks ); 791 } 792 793 /** 794 * @param xAxisLabelTransformer the xAxisLabelTransformer to set 795 */ 796 public void setxAxisLabelTransformer( final LabelTransformer xAxisLabelTransformer ) 797 { 798 this.xAxisConfig.getRenderingConfig().setLabelTransformer( xAxisLabelTransformer ); 799 } 800 801 /** 802 * @param yAxisLabelTransformer the yAxisLabelTransformer to set 803 */ 804 public void setyAxisLabelTransformer( final LabelTransformer yAxisLabelTransformer ) 805 { 806 this.yAxisConfig.getRenderingConfig().setLabelTransformer( yAxisLabelTransformer ); 807 } 808 809 /** 810 * @param drawMinorTickGrid the drawMinorTickGrid to set 811 */ 812 public void setDrawMinorTickGrid( final boolean drawMinorTickGrid ) 813 { 814 this.xAxisConfig.getRenderingConfig().setDrawMinorGrid( drawMinorTickGrid ); 815 this.yAxisConfig.getRenderingConfig().setDrawMinorGrid( drawMinorTickGrid ); 816 } 817 818 /** 819 * @param drawMajorTickGrid the drawMajorTickGrid to set 820 */ 821 public void setDrawMajorTickGrid( final boolean drawMajorTickGrid ) 822 { 823 this.xAxisConfig.getRenderingConfig().setDrawMajorGrid( drawMajorTickGrid ); 824 this.yAxisConfig.getRenderingConfig().setDrawMajorGrid( drawMajorTickGrid ); 825 } 826 827 /** 828 * @param minorGridColour the minorGridColour to set 829 */ 830 public void setMinorGridColour( final Q minorGridColour ) 831 { 832 this.xAxisConfig.getRenderingConfig().setMinorGridColour( minorGridColour ); 833 this.yAxisConfig.getRenderingConfig().setMinorGridColour( minorGridColour ); 834 } 835 836 /** 837 * @param majorGridColour the majorGridColour to set 838 */ 839 public void setMajorGridColour( final Q majorGridColour ) 840 { 841 this.xAxisConfig.getRenderingConfig().setMajorGridColour( majorGridColour ); 842 this.yAxisConfig.getRenderingConfig().setMajorGridColour( majorGridColour ); 843 } 844 845 /** 846 * @param majorGridThickness the majorGridThickness to set 847 */ 848 public void setMajorGridThickness( final int majorGridThickness ) 849 { 850 this.xAxisConfig.getRenderingConfig().setMajorGridThickness( majorGridThickness ); 851 this.yAxisConfig.getRenderingConfig().setMajorGridThickness( majorGridThickness ); 852 } 853 854 /** 855 * @param minorGridThickness the minorGridThickness to set 856 */ 857 public void setMinorGridThickness( final int minorGridThickness ) 858 { 859 this.xAxisConfig.getRenderingConfig().setMinorGridThickness( minorGridThickness ); 860 this.yAxisConfig.getRenderingConfig().setMinorGridThickness( minorGridThickness ); 861 } 862 863 /** 864 * Returns a data pixel transformer that is based on this axes renderer but has its values 865 * offset by the given number of pixels. 866 * 867 * // TODO: This method doesn't work at the moment 868 * 869 * @param xOffset The x location 870 * @param yOffset The y location 871 * @return A new data pixel transformer 872 */ 873 public DataUnitsTransformer<Q,double[],int[]> getRelativePixelTransformer( 874 final int xOffset, final int yOffset ) 875 { 876 // TODO: This needs completing 877 return new DataUnitsTransformer<Q,double[],int[]>() 878 { 879 @Override 880 public void precalc() 881 { 882 // TODO Auto-generated method stub 883 } 884 885 @Override 886 public int[] calculatePosition( final double[] units ) 887 { 888 // TODO Auto-generated method stub 889 return null; 890 } 891 892 @Override 893 public double[] calculateUnitsAt( final int[] position ) 894 { 895 // TODO Auto-generated method stub 896 return null; 897 } 898 899 @Override 900 public int[] scaleDimension( final double[] dimension ) 901 { 902 // TODO Auto-generated method stub 903 return null; 904 } 905 906// @Override 907// public void precalc( final double[] dim ) 908// { 909// AxesRenderer2D.this.precalc( dim ); 910// } 911// 912// @Override 913// public Point2d calculatePosition( final double[] dim, final double x, final double y ) 914// { 915// // Calculate the position of the data 916// final Point2d p = AxesRenderer2D.this.calculatePosition( dim, x, y ); 917// 918// // Then translate it back by the offset 919// p.translate( -xOffset, -yOffset ); 920// return p; 921// } 922// 923// @Override 924// public double[] calculateUnitsAt( final double[] dim, int x, int y ) 925// { 926// // Translate the pixel to the original coordinates 927// x += xOffset; 928// y += yOffset; 929// // Now calculate the value 930// return AxesRenderer2D.this.calculateUnitsAt( dim, x, y ); 931// } 932 }; 933 } 934 935 /** 936 * @return the xAxisConfig 937 */ 938 public AxisConfig<Q> getxAxisConfig() 939 { 940 return this.xAxisConfig; 941 } 942 943 /** 944 * @param xAxisConfig the xAxisConfig to set 945 */ 946 public void setxAxisConfig( final AxisConfig<Q> xAxisConfig ) 947 { 948 this.xAxisConfig = xAxisConfig; 949 } 950 951 /** 952 * @return the yAxisConfig 953 */ 954 public AxisConfig<Q> getyAxisConfig() 955 { 956 return this.yAxisConfig; 957 } 958 959 /** 960 * @param yAxisConfig the yAxisConfig to set 961 */ 962 public void setyAxisConfig( final AxisConfig<Q> yAxisConfig ) 963 { 964 this.yAxisConfig = yAxisConfig; 965 } 966 967 /** 968 * {@inheritDoc} 969 * @see org.openimaj.vis.DataUnitsTransformer#calculatePosition(java.lang.Object) 970 */ 971 @Override 972 public int[] calculatePosition( final double[] units ) 973 { 974 Point2dImpl p = new Point2dImpl( (float)units[0], (float)units[1] ); 975 p = p.transform( this.dataTransformMatrix ); 976 return new int[] { Math.round(p.getX()), Math.round(p.getY()) }; 977 978// final double[] dx = this.xAxisRenderer.calculatePosition( units[0] ); 979// final double[] dy = this.yAxisRenderer.calculatePosition( units[1] ); 980// 981// System.out.println( "units[0] = "+units[0]+" --> "+Arrays.toString( dx ) ); 982// System.out.println( "units[1] = "+units[1]+" --> "+Arrays.toString( dy ) ); 983// 984// return new int[] { (int) dx[0], (int)dy[1] }; 985// //(int)(dx[0]+dy[0]), (int)(dx[1]+dy[1]) }; 986 } 987 988 /** 989 * {@inheritDoc} 990 * @see org.openimaj.vis.DataUnitsTransformer#calculateUnitsAt(java.lang.Object) 991 */ 992 @Override 993 public double[] calculateUnitsAt( final int[] position ) 994 { 995 return new double[] { 996 this.xAxisRenderer.calculateUnitsAt( 997 new double[] {position[0],position[1]} ), 998 this.yAxisRenderer.calculateUnitsAt( 999 new double[] {position[0],position[1]} ) 1000 }; 1001 } 1002 1003 /** 1004 * Given two dimensions, returns the dimensions scaled to the appropriate sizes. 1005 * @param xs The x dimension 1006 * @param ys The y dimension 1007 * @return The scaled dimensions 1008 */ 1009 public double[] scaleDimensions( final double xs, final double ys ) 1010 { 1011 return new double[]{ 1012 xs * this.xAxisRenderer.getCurrentScale(), 1013 ys * this.yAxisRenderer.getCurrentScale() 1014 }; 1015 } 1016 1017 /** 1018 * {@inheritDoc} 1019 * @see org.openimaj.vis.DataUnitsTransformer#scaleDimension(java.lang.Object) 1020 */ 1021 @Override 1022 public int[] scaleDimension( final double[] dimension ) 1023 { 1024 return new int[] 1025 { 1026 (int)(dimension[0] * this.xAxisRenderer.getCurrentScale()), 1027 (int)(dimension[1] * this.yAxisRenderer.getCurrentScale()) 1028 }; 1029 } 1030 1031 /** 1032 * Helper function to calulate the render position of a data unit 1033 * @param x The data unit x 1034 * @param y The data unit y 1035 * @return The render position 1036 */ 1037 public Point2d calculatePosition( final double x, final double y ) 1038 { 1039 final int[] p = this.calculatePosition( new double[] {x, y} ); 1040 return new Point2dImpl( p[0], p[1] ); 1041 } 1042 1043 /** 1044 * Config may be null as it is not used. 1045 * 1046 * {@inheritDoc} 1047 * @see org.openimaj.vis.DataUnitsTransformer#precalc() 1048 */ 1049 @Override 1050 synchronized public void precalc() 1051 { 1052 // Set the position of the x axis 1053 final double[] xLoc = this.xAxisConfig.getLocation(); 1054 xLoc[0] = this.axisPaddingLeft; 1055 xLoc[1] = this.getxAxisPosition(); 1056 this.xAxisRenderer.precalc(); 1057 1058 // Calculate a data transform matrix for working out the position of data 1059 this.dataTransformMatrix = Matrix.identity( 3, 3 ); 1060 this.dataTransformMatrix = TransformUtilities.translateMatrix( 1061 -this.xAxisConfig.getMinValue(), 0 ).times( this.dataTransformMatrix ); 1062 this.dataTransformMatrix = TransformUtilities.scaleMatrix( 1063 this.xAxisRenderer.getCurrentScale(), -this.yAxisRenderer.getCurrentScale() ) 1064 .times( this.dataTransformMatrix ); 1065 this.dataTransformMatrix = TransformUtilities.rotationMatrix( 1066 this.xAxisConfig.getOrientation()[0] ).times( this.dataTransformMatrix ); 1067 this.dataTransformMatrix = TransformUtilities.translateMatrix( xLoc[0], xLoc[1] ) 1068 .times( this.dataTransformMatrix ); 1069 1070 // Re-seat the y axis 1071 final double[] yLoc = this.yAxisConfig.getLocation(); 1072 final Point2d dd = this.calculatePosition( 0, this.yAxisConfig.getMinValue() ); 1073 yLoc[0] = dd.getX(); 1074 yLoc[1] = dd.getY(); 1075 this.yAxisRenderer.precalc(); 1076 } 1077 1078 /** 1079 * @param image the image to set 1080 */ 1081 public void setImage( final I image ) 1082 { 1083 synchronized( this ) 1084 { 1085 this.xAxisRenderer.setImage( image ); 1086 this.yAxisRenderer.setImage( image ); 1087 1088 this.xAxisRenderer.setAxisLength( 1089 image.getWidth() - this.axisPaddingLeft - this.axisPaddingRight ); 1090 this.yAxisRenderer.setAxisLength( 1091 image.getHeight() - this.axisPaddingBottom - this.axisPaddingTop ); 1092 } 1093 } 1094 1095 /** 1096 * @return the xAxisRenderer 1097 */ 1098 public AxisRenderer2D<Q> getxAxisRenderer() 1099 { 1100 return this.xAxisRenderer; 1101 } 1102 1103 /** 1104 * @return the yAxisRenderer 1105 */ 1106 public AxisRenderer2D<Q> getyAxisRenderer() 1107 { 1108 return this.yAxisRenderer; 1109 } 1110 1111 /** 1112 * @param args 1113 */ 1114 public static void main( final String[] args ) 1115 { 1116 final MBFImage visImage = new MBFImage( 1000, 600, 3 ); 1117 final AxesRenderer2D<Float[],MBFImage> ar = new AxesRenderer2D<Float[],MBFImage>(); 1118 1119 ar.setxAxisColour( RGBColour.WHITE ); 1120 ar.setyAxisColour( RGBColour.WHITE ); 1121 ar.setMajorTickColour( RGBColour.WHITE ); 1122 ar.setMinorTickColour( RGBColour.GRAY ); 1123 ar.setxTickLabelColour( RGBColour.GRAY ); 1124 ar.setyTickLabelColour( RGBColour.GRAY ); 1125 ar.setxAxisNameColour( RGBColour.WHITE ); 1126 ar.setyAxisNameColour( RGBColour.WHITE ); 1127 1128 ar.setxAxisPosition( 100 ); 1129 ar.setMinXValue( -1 ); 1130 ar.setMaxXValue( 1 ); 1131 ar.setMinYValue( -5 ); 1132 ar.setMaxYValue( 1 ); 1133 ar.setDrawYAxis( true ); 1134 ar.setDrawXAxis( true ); 1135 ar.setDrawXAxisName( true ); 1136 ar.setDrawYAxisName( true ); 1137 ar.setDrawXTickLabels( true ); 1138 ar.setMinorTickLength( 5 ); 1139 ar.setMajorTickLength( 7 ); 1140 ar.setMajorTickThickness( 3 ); 1141 ar.setMinorTickThickenss( 1 ); 1142 ar.setxMinorTickSpacing( 0.2 ); 1143 ar.setxMajorTickSpacing( 1 ); 1144 ar.setxLabelSpacing( 0.25 ); 1145// ar.setxTickLabelFont( new GeneralFont( "Arial", java.awt.Font.PLAIN ) ); 1146 ar.setxTickLabelSize( 14 ); 1147 ar.setyMinorTickSpacing( 0.1 ); 1148 ar.setyMajorTickSpacing( 1 ); 1149 ar.setyLabelSpacing( 0.5 ); 1150// ar.setyTickLabelFont = new GeneralFont( "Arial", java.awt.Font.PLAIN ); 1151 ar.setyTickLabelSize( 14 ); 1152 ar.setxAxisName( "Stuff" ); 1153// ar.setxAxisNameFont = new GeneralFont( "Times New Roman", java.awt.Font.PLAIN ); 1154 ar.setxAxisNameSize( 25 ); 1155 ar.setyAxisName( "Things" ); 1156// ar.setyAxisNameFont = new GeneralFont( "Times New Roman", java.awt.Font.PLAIN ); 1157 ar.setyAxisNameSize( 25 ); 1158 1159 ar.precalc(); 1160 ar.renderAxis( visImage ); 1161 DisplayUtilities.display( visImage ); 1162 } 1163}