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; 034 035import javax.media.opengl.GL; 036import javax.media.opengl.GL2; 037import javax.media.opengl.GLAutoDrawable; 038import javax.media.opengl.fixedfunc.GLMatrixFunc; 039 040import org.openimaj.math.geometry.shape.Rectangle3D; 041 042/** 043 * Plots rectangles into a 3D space. 044 * 045 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 046 * @created 1 Aug 2013 047 * @version $Author$, $Revision$, $Date$ 048 */ 049public class Rectangle3DPlotter extends XYZVisualisation3D<Rectangle3D> implements ItemPlotter3D<Rectangle3D> 050{ 051 /** 052 * Where the actual position of the rectangle is relative to the geometry. 053 * 054 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 055 * @created 1 Aug 2013 056 * @version $Author$, $Revision$, $Date$ 057 */ 058 public static enum RectanglePlotPosition 059 { 060 /** Centre the rectangle on the data point */ 061 CENTRAL, 062 063 /** Put the top left of the rectangle on the data point */ 064 TOP_LEFT, 065 066 /** Put the bottom left of the rectangle on the data point */ 067 BOTTOM_LEFT, 068 069 /** Put the bottom right of the rectangle on the data point */ 070 BOTTOM_RIGHT, 071 072 /** Put the top right of the rectangle on the data point */ 073 TOP_RIGHT 074 } 075 076 /** The offset for the rectangle position */ 077 private final RectanglePlotPosition pos = RectanglePlotPosition.CENTRAL; 078 079 /** Whether to draw a dot at the point (only if centrally drawn) */ 080 private final boolean drawDotAtPoint = true; 081 082 /** 083 * Create a visualisation with the given size 084 * @param width Width in pixels of the vis 085 * @param height Height in pixels of the vis 086 */ 087 public Rectangle3DPlotter( final int width, final int height ) 088 { 089 super( width, height ); 090 super.setPlotter( this ); 091 } 092 093 /** 094 * {@inheritDoc} 095 * @see org.openimaj.vis.general.ItemPlotter3D#renderRestarting() 096 */ 097 @Override 098 public void renderRestarting() 099 { 100 } 101 102 /** 103 * {@inheritDoc} 104 * @see org.openimaj.vis.general.ItemPlotter3D#plotObject(javax.media.opengl.GLAutoDrawable, org.openimaj.vis.general.XYZVisualisation3D.LocatedObject3D, org.openimaj.vis.general.AxesRenderer3D) 105 */ 106 @Override 107 public void plotObject( final GLAutoDrawable drawable, final LocatedObject3D<Rectangle3D> object, 108 final AxesRenderer3D renderer ) 109 { 110 // object.object.x,y,z is where we plot the rectangle. 111 // object.x,y,z is the data point position. 112 final double[] p = renderer.calculatePosition( new double[] 113 { object.object.x, object.object.y, object.object.z } ); 114 final double[] p2 = renderer.calculatePosition( new double[] 115 { object.x, object.y, object.z } ); 116 117 final GL2 gl = drawable.getGL().getGL2(); 118 119 gl.glPushMatrix(); 120 121 // Translate to the position of the rectangle 122 gl.glMatrixMode( GLMatrixFunc.GL_MODELVIEW ); 123 gl.glTranslated( p2[0], p2[1], p2[2] ); 124 gl.glRotated( object.object.xRotation, 1, 0, 0 ); 125 gl.glRotated( object.object.yRotation, 0, 1, 0 ); 126 gl.glRotated( object.object.zRotation, 0, 0, 1 ); 127 128 final double[] dims = renderer.scaleDimension( new double[]{object.object.width,object.object.height,0} ); 129 final double w = dims[0]; 130 final double h = dims[1]; 131 132 gl.glBegin( GL.GL_LINE_LOOP ); 133 gl.glVertex3d( p2[0]-p[0], p2[1]-p[1], 0 ); 134 gl.glVertex3d( p2[0]-p[0]-w, p2[1]-p[1], 0 ); 135 gl.glVertex3d( p2[0]-p[0]-w, p2[1]-p[1]-h, 0 ); 136 gl.glVertex3d( p2[0]-p[0], p2[1]-p[1]-h, 0 ); 137 gl.glEnd(); 138 139 gl.glPopMatrix(); 140 141 if( this.pos == RectanglePlotPosition.CENTRAL && this.drawDotAtPoint ) 142 { 143 gl.glPushMatrix(); 144 gl.glMatrixMode( GLMatrixFunc.GL_MODELVIEW ); 145 gl.glBegin( GL.GL_POINTS ); 146 gl.glVertex3d( p2[0], p2[1], p2[2] ); 147 gl.glEnd(); 148 gl.glPopMatrix(); 149 } 150 } 151 152 @Override 153 public void init( final GLAutoDrawable drawable ) 154 { 155 super.init( drawable ); 156 157 final float eyeX = 0f, eyeY = 0.1f, eyeZ = 1f; 158 final float lookAtX = 0f, lookAtY = 0f, lookAtZ = 0f; 159 final float upX = 0, upY = 1, upZ = 0; 160 this.glu.gluLookAt( eyeX, eyeY, eyeZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ ); 161 162 // Instantiate the camera mover 163 this.cameraPosition = new RotatingCameraProvider( 164 eyeX, eyeY, eyeZ, 165 lookAtX, lookAtY, lookAtZ, 166 0.0004f, 0.0001f, 0.00001f, 1f, 1f, 1f ); 167 } 168 169 /** 170 * Note that your rectangle may be altered at this point. Pass in a clone 171 * if you don't want it to get changed. 172 * 173 * @param rect The rectangle. 174 */ 175 public void addRectangle( final Rectangle3D rect ) 176 { 177 final double x = rect.x, y = rect.y, z = rect.z; 178 switch( this.pos ) 179 { 180 case CENTRAL: 181 rect.x -= rect.width/2; 182 rect.y -= rect.height/2; 183 break; 184 case TOP_LEFT: 185 break; 186 case TOP_RIGHT: 187 rect.x -= rect.width; 188 break; 189 case BOTTOM_LEFT: 190 rect.y -= rect.height; 191 break; 192 case BOTTOM_RIGHT: 193 rect.x -= rect.width; 194 rect.y -= rect.height; 195 break; 196 } 197 198 super.data.add( new LocatedObject3D<Rectangle3D>( x, y, z, rect ) ); 199 } 200 201 /** 202 * 203 * @param args 204 */ 205 public static void main( final String[] args ) 206 { 207 final Rectangle3DPlotter rp = new Rectangle3DPlotter( 1000, 800 ); 208 rp.getAxesRenderer().setAxesRanges( -1, 1, -1, 1, -1, 1 ); 209 210 final int n = 40; 211 for( int i = 0; i < n ; i++ ) 212 { 213 final Rectangle3D r = new Rectangle3D(); 214 r.x = (float)(Math.random()*2-1); 215 r.y = (float)(Math.random()*2-1); 216 r.z = (float)(Math.random()*2-1); 217 r.width = (float)(Math.random()/2); 218 r.height = r.width; 219 r.xRotation = Math.random() * 90; 220 r.yRotation = Math.random() * 90; 221 r.zRotation = Math.random() * 90; 222 223 System.out.println( "Rect "+i+" = "+r ); 224 225 rp.addRectangle( r ); 226 } 227 } 228}