arcgissamples\display\ShowHUDCommand.java
/* Copyright 2010 ESRI * * All rights reserved under the copyright laws of the United States * and applicable international laws, treaties, and conventions. * * You may freely redistribute and use this sample code, with or * without modification, provided you include the original copyright * notice and use restrictions. * * See the use restrictions. * */ package arcgissamples.display; import java.io.IOException; import java.text.DecimalFormat; import java.text.NumberFormat; import javax.media.opengl.GL; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import com.esri.arcgis.controls.BaseCommand; import com.esri.arcgis.controls.HookHelper; import com.esri.arcgis.display.DisplayTransformation; import com.esri.arcgis.display.IDisplay; import com.esri.arcgis.display.IDynamicDisplay; import com.esri.arcgis.display.IDynamicDrawScreen; import com.esri.arcgis.display.IDynamicGlyph; import com.esri.arcgis.display.IDynamicGlyphFactory; import com.esri.arcgis.display.IDynamicMapEventsAdapter; import com.esri.arcgis.display.IDynamicMapEventsAfterDynamicDrawEvent; import com.esri.arcgis.display.IDynamicSymbolProperties; import com.esri.arcgis.display.ISymbol; import com.esri.arcgis.display.ITextSymbol; import com.esri.arcgis.display.TextSymbol; import com.esri.arcgis.display.esriDynamicMapDrawPhase; import com.esri.arcgis.display.esriDynamicSymbolRotationAlignment; import com.esri.arcgis.display.esriDynamicSymbolType; import com.esri.arcgis.display.esriTextHorizontalAlignment; import com.esri.arcgis.display.esriTextVerticalAlignment; import com.esri.arcgis.system.tagRECT; import com.esri.arcgis.geometry.IPoint; import com.esri.arcgis.geometry.Point; import com.esri.arcgis.interop.AutomationException; class ShowHUDCommand extends BaseCommand { private static final long serialVersionUID = 1L; private boolean checked = false; @Override public boolean isChecked() { return this.checked; } private HookHelper captainHook; public void onCreate(Object hook) { try { this.captainHook = new HookHelper(); this.captainHook.setHookByRef(hook); } catch (Exception e) { e.printStackTrace(); } this.caption = "Show HUD"; this.enabled = true; this.name = "Show HUD"; } @Override public void onClick() { this.checked = !this.checked; try { com.esri.arcgis.carto.Map map = (com.esri.arcgis.carto.Map) captainHook .getFocusMap(); if (this.checked) { //Enable dynamic mode map.setDynamicMapEnabled(true); //Add the dynamic map events listener //This is where we draw the HUD in the AfterDynamicDraw event. map.addIDynamicMapEventsListener(new IDynamicMapEventsAdapter() { private static final long serialVersionUID = 1L; private GL gl = null; private GLContext context = null; private IDisplay Display; private tagRECT deviceFrame; private DisplayTransformation displayXformation; private IDynamicGlyph textGlyph = null; private IDynamicGlyphFactory glyphFactory = null; private IDynamicDrawScreen drawScreen = null; private IDynamicSymbolProperties symbolProperties = null; private IPoint anchor = null; private NumberFormat formatter; public void afterDynamicDraw( IDynamicMapEventsAfterDynamicDrawEvent theEvent) throws IOException, AutomationException { if (theEvent.getDynamicMapDrawPhase() != esriDynamicMapDrawPhase.esriDMDPDynamicLayers) return; Display = theEvent.getDisplay(); displayXformation = (DisplayTransformation) Display .getDisplayTransformation(); // get the device frame size deviceFrame = displayXformation.getDeviceFrame(); float rotation = (float) displayXformation .getRotation(); try { if (context == null) { // Tell JOGL that we are going to use // our own OpenGL Context context = GLDrawableFactory.getFactory() .createExternalGLContext(); context.makeCurrent(); gl = context.getGL(); // need to cache all the DynamicDisplay // stuff IDynamicDisplay dynamicDisplay = theEvent .getDynamicDisplay(); glyphFactory = dynamicDisplay .getDynamicGlyphFactory(); drawScreen = (IDynamicDrawScreen) dynamicDisplay; symbolProperties = (IDynamicSymbolProperties) dynamicDisplay; // set the screen coordinates of the // char symbol anchor = new Point(); textGlyph = createDynamicGlyphs(glyphFactory); formatter = DecimalFormat .getNumberInstance(); formatter.setMaximumFractionDigits(2); } // draw the OpenGL compass gl.glPushMatrix(); gl.glLoadIdentity(); // use OpenGL to do the drawings drawTicks(deviceFrame, rotation); gl.glPopMatrix(); // please note that while you are rotating the // map, the numbers showing in the HUD are // different than the number reported by the // rotation tool. The reason for that is that // the reportad map rotation is the mathematical // angle while the HUD shows the angle from // the north (the map's azimuth). drawAzimuths(deviceFrame, rotation); } catch (Exception e) { e.printStackTrace(); } } private void drawAzimuths(tagRECT deviceFrame, float angle) throws Exception { // need to draw the current azimuth symbolProperties.setColor( esriDynamicSymbolType.esriDSymbolText, 0.0f, 0.8f, 0.0f, 1.0f); // Green // assign the item's glyph to the dynamic-symbol symbolProperties.setDynamicGlyphByRef( esriDynamicSymbolType.esriDSymbolText, textGlyph); // get the floor of the azimuth float azimuth = 360.0f - angle; float floorAzi = (int) (azimuth / 10.0f) * 10.0f; double deltaAzi = (angle - (float) ((int) (angle / 10.0f) * 10.0f)) * 6.0; // (the // shift // to // the // X // axis) double xmin = (double) deviceFrame.left; double xmax = (double) deviceFrame.right; double ymin = (double) deviceFrame.top; double xmiddle = (xmax + xmin) / 2.0; double x = xmiddle - 150.0 + deltaAzi; double dAzStartMiddle = (150.0 - 2.0 * deltaAzi) / 6.0; dAzStartMiddle = (int) (dAzStartMiddle / 60.0) * 60.0 + 10.0; int azi = (int) (floorAzi - dAzStartMiddle) - 5; double delta = 60.0; symbolProperties.setHeading( esriDynamicSymbolType.esriDSymbolText, 0.0f); symbolProperties .setRotationAlignment( esriDynamicSymbolType.esriDSymbolText, esriDynamicSymbolRotationAlignment.esriDSRAScreen); for (int i = 0; i < 5; i++) { anchor.putCoords(x, ymin + 28.0); if (azi > 360) azi -= 360; else if (azi < 0) azi += 360; drawScreen.drawScreenText(anchor, new Integer( azi).toString()); azi += 10; x += delta; } // need to draw the current azimuth symbolProperties.setColor( esriDynamicSymbolType.esriDSymbolText, 0.0f, 0.0f, 0.0f, 1.0f); // Black anchor.putCoords(xmiddle, ymin + 95.0); drawScreen.drawScreenText(anchor, formatter .format(azimuth)); } private void drawTicks(tagRECT deviceFrame2, float azimuth) { // get the floor of the azimuth float floorAzi = (int) (azimuth / 10.0f) * 10.0f; float deltaAzi = (azimuth - floorAzi) * 6.0f; float deltaAziSmall = (azimuth - ((int) (azimuth / 2.0f) * 2.0f)) * 6.0f; float delta = 60.0f; float deltaSmall = 12.0f; float xmin = (float) deviceFrame.left; float xmax = (float) deviceFrame.right; float ymin = (float) deviceFrame.top; float xmiddle = (xmax + xmin) / 2.0f; gl.glDisable(GL.GL_TEXTURE_2D); // draw a line from left to right gl.glColor3f(0.0f, 0.5f, 0.0f); gl.glLineWidth(1.5f); gl.glBegin(GL.GL_LINES); gl.glVertex2f(xmiddle - 150.0f, ymin + 40.0f); gl.glVertex2f(xmiddle + 150.0f, ymin + 40.0f); gl.glEnd(); // draw the 10 degrees big ticks float x = xmiddle - 150.0f + deltaAzi; for (int i = 0; i < 5; i++) { gl.glBegin(GL.GL_LINES); gl.glVertex2f(x, ymin + 40.0f); gl.glVertex2f(x, ymin + 80.0f); gl.glEnd(); x += delta; } // draw the 2 degrees small ticks x = xmiddle - 150.0f + deltaAziSmall; gl.glLineWidth(1.0f); for (int i = 0; i < 25; i++) { gl.glBegin(GL.GL_LINES); gl.glVertex2f(x, ymin + 40.0f); gl.glVertex2f(x, ymin + 60.0f); gl.glEnd(); x += deltaSmall; } gl.glLineWidth(2.0f); gl.glColor3f(0.0f, 0.0f, 0.0f); gl.glBegin(GL.GL_TRIANGLES); gl.glVertex2f(xmiddle, ymin + 40.0f); gl.glVertex2f(xmiddle - 8.0f, ymin + 60.0f); gl.glVertex2f(xmiddle + 8.0f, ymin + 60.0f); gl.glEnd(); gl.glEnable(GL.GL_TEXTURE_2D); } private IDynamicGlyph createDynamicGlyphs( IDynamicGlyphFactory glyphFactory) { try { // create the text glyph using a text symbol ITextSymbol textSymbol = new TextSymbol(); textSymbol.setSize(15.0); textSymbol.setAngle(0.0); textSymbol .setVerticalAlignment(esriTextVerticalAlignment.esriTVACenter); textSymbol .setHorizontalAlignment(esriTextHorizontalAlignment.esriTHACenter); return glyphFactory .createDynamicGlyph((ISymbol) textSymbol); } catch (Exception e) { e.printStackTrace(); return null; } } }); } else { //Disable dynamic mode map.setDynamicMapEnabled(false); } this.captainHook.getActiveView().getScreenDisplay().updateWindow(); } catch (Exception e) { e.printStackTrace(); } } }