/**
   * Z-Sorts and draws all 3D objects which have been added to the collection of objects to draw via
   * the add3DObject() method.
   *
   * @param g the Graphics on which to draw the 3D objects.
   */
  public void drawObjectsOnThis(Graphics g) {
    synchronized (objects) {
      // calculate all rotations
      for (Iterator<Object3D> it = objects.iterator(); it.hasNext(); ) {
        Object3D currentObject = it.next();
        // very rarely, when the "objects" list is being modified by
        // another thread, "currentObject" is null here
        if (currentObject != null) currentObject.calculateRotation(window);
        else
          // if we are here, then that strange thread error has
          // occurred, and it causes an exception to be thrown
          // when
          // Collections.sort() is called later, so just
          // return now to prevent further errors
          return;
      }

      // Z-Sort
      Collections.sort(objects, depthComparator);

      // Draw all objects
      Graphics2D g2D = (Graphics2D) g;
      for (Iterator<Object3D> it = objects.iterator(); it.hasNext(); ) it.next().drawOnThis(g2D);
    }
  }
  /**
   * Figures out the object which, when drawn on the screen, the specified point is "inside"
   *
   * @param point the point to look for objects under
   * @return the object which, when drawn on the screen, the specified point is "inside", or null if
   *     the point is not over an object.
   */
  public Object3D getObjectWhichContainsPoint(Point point) {

    for (Iterator<Object3D> it = objects.iterator(); it.hasNext(); ) {
      Object3D currentObject = it.next();
      if (currentObject.contains(point)) return currentObject;
    }

    return null;
  }
  /**
   * Z-Sorts and draws all 3D objects which have been added to the collection of objects to draw via
   * the add3DObject() method. The progress of the drawing is instrumented with the specified
   * progress monitor.
   *
   * @param g the Graphics on which to draw the 3D objects.
   * @param progressMonitor the progress monitor which will be updated with the progress of drawing
   *     the objects. If the progress dialog is cancelled, then the drawing stops.
   */
  public void drawObjectsOnThis(Graphics g, ProgressMonitor progressMonitor) {
    synchronized (objects) {
      progressMonitor.setProgress(1);
      progressMonitor.setNote("Calculating rotations...");
      for (Iterator<Object3D> it = objects.iterator(); it.hasNext(); ) {
        Object3D currentObject = it.next();
        // check for cancellation
        if (progressMonitor.isCanceled()) return;

        // very rarely, when the "objects" list is being modified by
        // another thread, "currentObject" here is null
        if (currentObject != null) currentObject.calculateRotation(window);
        else
          // if we are here, then that strange thread error has
          // occurred, and it causes an exception to be thrown when
          // Collections.sort() is called later, so just
          // return now to prevent further errors
          return;
      }

      progressMonitor.setNote("Z-Sorting...");
      // Z-Sort
      Collections.sort(objects, depthComparator);

      // Draw all objects
      Graphics2D g2D = (Graphics2D) g;
      double numberOfObjects = (double) objects.size();
      double currentIndex = 1;

      progressMonitor.setNote("Drawing objects...");
      int maxProgress = progressMonitor.getMaximum();
      for (Iterator<Object3D> it = objects.iterator(); it.hasNext(); ) {
        // check for cancellation
        if (progressMonitor.isCanceled()) return;
        else {
          progressMonitor.setProgress((int) (currentIndex++ / numberOfObjects * maxProgress));
          it.next().drawOnThis(g2D);
        }
      }
    }
  }