Example #1
0
  // Draw the scale label
  private void drawLabel(DrawContext dc, String text, Vec4 screenPoint) {
    TextRenderer textRenderer =
        OGLTextRenderer.getOrCreateTextRenderer(dc.getTextRendererCache(), this.defaultFont);

    Rectangle2D nameBound = textRenderer.getBounds(text);
    int x = (int) (screenPoint.x() - nameBound.getWidth() / 2d);
    int y = (int) screenPoint.y();

    textRenderer.begin3DRendering();

    textRenderer.setColor(this.getBackgroundColor(this.color));
    textRenderer.draw(text, x + 1, y - 1);
    textRenderer.setColor(this.color);
    textRenderer.draw(text, x, y);

    textRenderer.end3DRendering();
  }
  /**
   * Compute the label's screen position from its geographic position.
   *
   * @param dc Current draw context.
   */
  protected void computeGeometry(DrawContext dc) {
    // Project the label position onto the viewport
    Position pos = this.getPosition();
    if (pos == null) return;

    this.placePoint = dc.computeTerrainPoint(pos.getLatitude(), pos.getLongitude(), 0);
    this.screenPlacePoint = dc.getView().project(this.placePoint);

    this.eyeDistance = this.placePoint.distanceTo3(dc.getView().getEyePoint());

    boolean orientationReversed = false;
    if (this.orientationPosition != null) {
      // Project the orientation point onto the screen
      Vec4 orientationPlacePoint =
          dc.computeTerrainPoint(
              this.orientationPosition.getLatitude(), this.orientationPosition.getLongitude(), 0);
      Vec4 orientationScreenPoint = dc.getView().project(orientationPlacePoint);

      this.rotation = this.computeRotation(this.screenPlacePoint, orientationScreenPoint);

      // The orientation is reversed if the orientation point falls to the right of the screen
      // point. Text is
      // never drawn upside down, so when the orientation is reversed the text flips vertically to
      // keep the text
      // right side up.
      orientationReversed = (orientationScreenPoint.x <= this.screenPlacePoint.x);
    }

    this.computeBoundsIfNeeded(dc);

    Offset offset = this.getOffset();
    Point2D offsetPoint =
        offset.computeOffset(this.bounds.getWidth(), this.bounds.getHeight(), null, null);

    // If a rotation is applied to the text, then rotate the offset as well. An offset in the x
    // direction
    // will move the text along the orientation line, and a offset in the y direction will move the
    // text
    // perpendicular to the orientation line.
    if (this.rotation != null) {
      double dy = offsetPoint.getY();

      // If the orientation is reversed we need to adjust the vertical offset to compensate for the
      // flipped
      // text. For example, if the offset normally aligns the top of the text with the place point
      // then without
      // this adjustment the bottom of the text would align with the place point when the
      // orientation is
      // reversed.
      if (orientationReversed) {
        dy = -(dy + this.bounds.getHeight());
      }

      Vec4 pOffset = new Vec4(offsetPoint.getX(), dy);
      Matrix rot = Matrix.fromRotationZ(this.rotation.multiply(-1));

      pOffset = pOffset.transformBy3(rot);

      offsetPoint = new Point((int) pOffset.getX(), (int) pOffset.getY());
    }

    int x = (int) (this.screenPlacePoint.x + offsetPoint.getX());
    int y = (int) (this.screenPlacePoint.y - offsetPoint.getY());

    this.screenPoint = new Point(x, y);
    this.screenExtent = this.computeTextExtent(x, y, this.rotation);
  }
Example #3
0
  // Rendering
  public void draw(DrawContext dc) {
    GL gl = dc.getGL();

    boolean attribsPushed = false;
    boolean modelviewPushed = false;
    boolean projectionPushed = false;

    try {
      gl.glPushAttrib(
          GL.GL_DEPTH_BUFFER_BIT
              | GL.GL_COLOR_BUFFER_BIT
              | GL.GL_ENABLE_BIT
              | GL.GL_TEXTURE_BIT
              | GL.GL_TRANSFORM_BIT
              | GL.GL_VIEWPORT_BIT
              | GL.GL_CURRENT_BIT);
      attribsPushed = true;

      gl.glDisable(GL.GL_TEXTURE_2D); // no textures

      gl.glEnable(GL.GL_BLEND);
      gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
      gl.glDisable(GL.GL_DEPTH_TEST);

      double width = this.size.width;
      double height = this.size.height;

      // Load a parallel projection with xy dimensions (viewportWidth, viewportHeight)
      // into the GL projection matrix.
      java.awt.Rectangle viewport = dc.getView().getViewport();
      gl.glMatrixMode(javax.media.opengl.GL.GL_PROJECTION);
      gl.glPushMatrix();
      projectionPushed = true;
      gl.glLoadIdentity();
      double maxwh = width > height ? width : height;
      gl.glOrtho(0d, viewport.width, 0d, viewport.height, -0.6 * maxwh, 0.6 * maxwh);

      gl.glMatrixMode(GL.GL_MODELVIEW);
      gl.glPushMatrix();
      modelviewPushed = true;
      gl.glLoadIdentity();

      // Scale to a width x height space
      // located at the proper position on screen
      double scale = this.computeScale(viewport);
      Vec4 locationSW = this.computeLocation(viewport, scale);
      gl.glTranslated(locationSW.x(), locationSW.y(), locationSW.z());
      gl.glScaled(scale, scale, 1);

      // Compute scale size in real world
      Position referencePosition = dc.getViewportCenterPosition();
      if (referencePosition != null) {
        Vec4 groundTarget = dc.getGlobe().computePointFromPosition(referencePosition);
        Double distance = dc.getView().getEyePoint().distanceTo3(groundTarget);
        this.pixelSize = dc.getView().computePixelSizeAtDistance(distance);
        Double scaleSize = this.pixelSize * width * scale; // meter
        String unitLabel = "m";
        if (this.unit.equals(UNIT_METRIC)) {
          if (scaleSize > 10000) {
            scaleSize /= 1000;
            unitLabel = "Km";
          }
        } else if (this.unit.equals(UNIT_IMPERIAL)) {
          scaleSize *= 3.280839895; // feet
          unitLabel = "ft";
          if (scaleSize > 5280) {
            scaleSize /= 5280;
            unitLabel = "mile(s)";
          }
        }

        // Rounded division size
        int pot = (int) Math.floor(Math.log10(scaleSize));
        if (!Double.isNaN(pot)) {
          int digit = Integer.parseInt(String.format("%.0f", scaleSize).substring(0, 1));
          double divSize = digit * Math.pow(10, pot);
          if (digit >= 5) divSize = 5 * Math.pow(10, pot);
          else if (digit >= 2) divSize = 2 * Math.pow(10, pot);
          double divWidth = width * divSize / scaleSize;

          // Draw scale
          if (!dc.isPickingMode()) {
            // Set color using current layer opacity
            Color backColor = this.getBackgroundColor(this.color);
            float[] colorRGB = backColor.getRGBColorComponents(null);
            gl.glColor4d(
                colorRGB[0],
                colorRGB[1],
                colorRGB[2],
                (double) backColor.getAlpha() / 255d * this.getOpacity());
            gl.glTranslated((width - divWidth) / 2, 0d, 0d);
            this.drawScale(dc, divWidth, height);

            colorRGB = this.color.getRGBColorComponents(null);
            gl.glColor4d(colorRGB[0], colorRGB[1], colorRGB[2], this.getOpacity());
            gl.glTranslated(-1d / scale, 1d / scale, 0d);
            this.drawScale(dc, divWidth, height);

            // Draw label
            String label = String.format("%.0f ", divSize) + unitLabel;
            gl.glLoadIdentity();
            gl.glDisable(GL.GL_CULL_FACE);
            drawLabel(
                dc,
                label,
                locationSW.add3(
                    new Vec4(divWidth * scale / 2 + (width - divWidth) / 2, height * scale, 0)));
          } else {
            // Picking
            this.pickSupport.clearPickList();
            this.pickSupport.beginPicking(dc);
            // Draw unique color across the map
            Color color = dc.getUniquePickColor();
            int colorCode = color.getRGB();
            // Add our object(s) to the pickable list
            this.pickSupport.addPickableObject(colorCode, this, referencePosition, false);
            gl.glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue());
            gl.glTranslated((width - divWidth) / 2, 0d, 0d);
            this.drawRectangle(dc, divWidth, height);
            // Done picking
            this.pickSupport.endPicking(dc);
            this.pickSupport.resolvePick(dc, dc.getPickPoint(), this);
          }
        }
      }
    } finally {
      if (projectionPushed) {
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glPopMatrix();
      }
      if (modelviewPushed) {
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glPopMatrix();
      }
      if (attribsPushed) gl.glPopAttrib();
    }
  }