/**
   * Construct a GraphicsModeControlJ3D associated with the input display
   *
   * @param d display associated with this GraphicsModeControlJ3D
   */
  public GraphicsModeControlJ3D(DisplayImpl d) {
    super(d);
    lineWidth = 1.0f;
    pointSize = 1.0f;
    lineStyle = SOLID_STYLE;
    pointMode = false;
    textureEnable = true;
    scaleEnable = false;
    // NICEST, FASTEST and BLENDED do not solve the depth precedence problem
    // note SCREEN_DOOR does not seem to work with variable transparency
    // transparencyMode = TransparencyAttributes.NICEST;
    transparencyMode = TransparencyAttributes.FASTEST;
    // transparencyMode = TransparencyAttributes.BLENDED;
    // transparencyMode = TransparencyAttributes.SCREEN_DOOR;
    polygonMode = PolygonAttributes.POLYGON_FILL;
    polygonOffset = Float.NaN;
    polygonOffsetFactor = 0f;
    adjustProjectionSeam = true;
    texture3DMode = STACK2D;

    projectionPolicy = View.PERSPECTIVE_PROJECTION;
    DisplayRendererJ3D displayRenderer = (DisplayRendererJ3D) getDisplayRenderer();
    if (displayRenderer != null) {
      if (displayRenderer.getMode2D()) {
        projectionPolicy = View.PARALLEL_PROJECTION;
        // for some strange reason, if we set PERSPECTIVE_PROJECTION at this
        // point, we can never set PARALLEL_PROJECTION
        displayRenderer.getView().setProjectionPolicy(projectionPolicy);
      }
    }
  }
 /**
  * Sets the antialiasing flag for the display.
  *
  * @param flag true to enable antialiasing
  * @throws VisADException a VisAD error occurred
  * @throws RemoteException change policy on remote display
  */
 public void setSceneAntialiasingEnable(boolean flag) throws VisADException, RemoteException {
   if (flag == anti_alias_flag) return;
   anti_alias_flag = flag;
   DisplayRendererJ3D displayRenderer = (DisplayRendererJ3D) getDisplayRenderer();
   if (displayRenderer != null) {
     displayRenderer.getView().setSceneAntialiasingEnable(anti_alias_flag);
   }
   changeControl(true);
   getDisplay().reDisplayAll();
 }
  /**
   * Set the line width used for LineAttributes. Calls changeControl and resets the display.
   *
   * @param width width to use (>= 1.0)
   * @throws VisADException couldn't set the line width on local display
   * @throws RemoteException couldn't set the line width on remote display
   */
  public void setLineWidth(float width) throws VisADException, RemoteException {
    if (width < 1.0f) width = 1.0f;
    if (Util.isApproximatelyEqual(lineWidth, width)) return;
    lineWidth = width;

    // WLH 2 Dec 2002 in response to qomo2.txt
    DisplayRendererJ3D dr = (DisplayRendererJ3D) getDisplayRenderer();
    dr.setLineWidth(width);

    changeControl(true);
    getDisplay().reDisplayAll();
  }
 /**
  * Sets the projection policy for the display. PARALLEL_PROJECTION will display a parallel view
  * while PERSPECTIVE_PROJECTION will create a perspective view. The default is a perspective view.
  *
  * @param policy policy to be used (DisplayImplJ3D.PARALLEL_PROJECTION or
  *     DisplayImplJ3D.PERSPECTIVE_PROJECTION
  * @throws VisADException bad policy or can't create the necessary VisAD object
  * @throws RemoteException change policy on remote display
  */
 public void setProjectionPolicy(int policy) throws VisADException, RemoteException {
   if (policy == projectionPolicy) return;
   if (policy == View.PARALLEL_PROJECTION || policy == View.PERSPECTIVE_PROJECTION) {
     projectionPolicy = policy;
     DisplayRendererJ3D displayRenderer = (DisplayRendererJ3D) getDisplayRenderer();
     if (displayRenderer != null) {
       displayRenderer.getView().setProjectionPolicy(projectionPolicy);
     }
     changeControl(true);
     getDisplay().reDisplayAll();
   } else {
     throw new DisplayException("GraphicsModeControlJ3D." + "setProjectionPolicy: bad policy");
   }
 }
  /**
   * Copy the state of a remote control to this control
   *
   * @param rmt remote control to sync with this one
   * @throws VisADException rmt == null or rmt is not a GraphicsModeControlJ3D or couldn't tell if
   *     control was changed.
   */
  public void syncControl(Control rmt) throws VisADException {
    if (rmt == null) {
      throw new VisADException(
          "Cannot synchronize " + getClass().getName() + " with null Control object");
    }

    if (!(rmt instanceof GraphicsModeControlJ3D)) {
      throw new VisADException(
          "Cannot synchronize " + getClass().getName() + " with " + rmt.getClass().getName());
    }

    GraphicsModeControlJ3D rmtCtl = (GraphicsModeControlJ3D) rmt;

    boolean changed = false;
    boolean redisplay = false;

    if (!Util.isApproximatelyEqual(lineWidth, rmtCtl.lineWidth)) {
      changed = true;
      redisplay = true;
      lineWidth = rmtCtl.lineWidth;
    }
    if (!Util.isApproximatelyEqual(pointSize, rmtCtl.pointSize)) {
      changed = true;
      redisplay = true;
      pointSize = rmtCtl.pointSize;
    }

    if (pointMode != rmtCtl.pointMode) {
      changed = true;
      redisplay = true;
      pointMode = rmtCtl.pointMode;
    }
    if (textureEnable != rmtCtl.textureEnable) {
      changed = true;
      redisplay = true;
      textureEnable = rmtCtl.textureEnable;
    }
    if (scaleEnable != rmtCtl.scaleEnable) {
      changed = true;
      getDisplayRenderer().setScaleOn(scaleEnable);
      scaleEnable = rmtCtl.scaleEnable;
    }

    if (transparencyMode != rmtCtl.transparencyMode) {
      changed = true;
      redisplay = true;
      transparencyMode = rmtCtl.transparencyMode;
    }

    if (adjustProjectionSeam != rmtCtl.adjustProjectionSeam) {
      changed = true;
      redisplay = true;
      adjustProjectionSeam = rmtCtl.adjustProjectionSeam;
    }

    if (texture3DMode != rmtCtl.texture3DMode) {
      changed = true;
      redisplay = true;
      texture3DMode = rmtCtl.texture3DMode;
    }

    if (cacheAppearances != rmtCtl.cacheAppearances) {
      changed = true;
      cacheAppearances = rmtCtl.cacheAppearances;
    }

    if (mergeGeometries != rmtCtl.mergeGeometries) {
      changed = true;
      mergeGeometries = rmtCtl.mergeGeometries;
    }

    if (projectionPolicy != rmtCtl.projectionPolicy) {
      changed = true;
      redisplay = true;
      projectionPolicy = rmtCtl.projectionPolicy;

      DisplayRendererJ3D displayRenderer;
      displayRenderer = (DisplayRendererJ3D) getDisplayRenderer();
      if (displayRenderer != null) {
        displayRenderer.getView().setProjectionPolicy(projectionPolicy);
      }
    }
    if (polygonMode != rmtCtl.polygonMode) {
      changed = true;
      polygonMode = rmtCtl.polygonMode;
    }

    if (missingTransparent != rmtCtl.missingTransparent) {
      changed = true;
      missingTransparent = rmtCtl.missingTransparent;
    }

    if (curvedSize != rmtCtl.curvedSize) {
      changed = true;
      curvedSize = rmtCtl.curvedSize;
    }

    if (!Util.isApproximatelyEqual(polygonOffset, rmtCtl.polygonOffset)) {
      changed = true;
      polygonOffset = rmtCtl.polygonOffset;
    }

    if (!Util.isApproximatelyEqual(polygonOffsetFactor, rmtCtl.polygonOffsetFactor)) {
      changed = true;
      polygonOffsetFactor = rmtCtl.polygonOffsetFactor;
    }

    if (anti_alias_flag != rmtCtl.anti_alias_flag) {
      changed = true;
      anti_alias_flag = rmtCtl.anti_alias_flag;
    }

    if (colorMode != rmtCtl.colorMode) {
      changed = true;
      colorMode = rmtCtl.colorMode;
    }

    if (lineStyle != rmtCtl.lineStyle) {
      changed = true;
      lineStyle = rmtCtl.lineStyle;
    }

    if (changed) {
      try {
        changeControl(true);
      } catch (RemoteException re) {
        throw new VisADException(
            "Could not indicate that control" + " changed: " + re.getMessage());
      }
    }
    if (redisplay) {
      getDisplay().reDisplayAll();
    }
  }