Package org.jmol.shapespecial

Source Code of org.jmol.shapespecial.DrawRenderer

/* $RCSfile$
* $Author: hansonr $
* $Date: 2006-02-25 11:44:18 -0600 (Sat, 25 Feb 2006) $
* $Revision: 4528 $
*
* Copyright (C) 2005  Miguel, Jmol Development
*
* Contact: jmol-developers@lists.sf.net, jmol-developers@lists.sourceforge.net
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License as published by the Free Software Foundation; either
*  version 2.1 of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jmol.shapespecial;


import java.util.List;

import javax.vecmath.AxisAngle4f;
import javax.vecmath.Matrix3f;
import javax.vecmath.Point3f;
import javax.vecmath.Point3i;
import javax.vecmath.Vector3f;

import org.jmol.g3d.Graphics3D;
import org.jmol.shape.MeshRenderer;
import org.jmol.viewer.ActionManager;
import org.jmol.viewer.JmolConstants;

public class DrawRenderer extends MeshRenderer {

  private int drawType;
  private DrawMesh dmesh;
 
  private Point3f[] controlHermites;
  private final Point3f vpt0 = new Point3f();
  private final Point3f vpt1 = new Point3f();
  private final Point3f vpt2 = new Point3f();
  private final Vector3f vTemp = new Vector3f();
  private final Vector3f vTemp2 = new Vector3f();

  protected void render() {
    /*
     * Each drawn object, draw.meshes[i], may consist of several polygons, one
     * for each MODEL FRAME. Or, it may be "fixed" and only contain one single
     * polygon.
     *
     */
    imageFontScaling = viewer.getImageFontScaling();
    Draw draw = (Draw) shape;
    for (int i = draw.meshCount; --i >= 0;)
      if (render1(dmesh = (DrawMesh) draw.meshes[i]))
        renderInfo();
  }
 
  protected boolean isPolygonDisplayable(int i) {
    return Draw.isPolygonDisplayable(dmesh, i)
        && (dmesh.modelFlags == null || dmesh.bsMeshesVisible.get(i));
  }
 
  protected void render2(boolean isExport) {
    drawType = dmesh.drawType;
    diameter = dmesh.diameter;
    width = dmesh.width;
    if (mesh.lineData != null) {
      drawLineData(mesh.lineData);
      return;
    }
    boolean isDrawPickMode = (viewer.getPickingMode() == ActionManager.PICKING_DRAW);
    int nPoints = vertexCount;
    boolean isCurved = (
        (drawType == JmolConstants.DRAW_CURVE
            || drawType == JmolConstants.DRAW_ARROW
            || drawType == JmolConstants.DRAW_ARC)
        && vertexCount >= 2);
    boolean isSegments = (drawType == JmolConstants.DRAW_LINE_SEGMENT);
    if (width > 0 && isCurved) {
      pt1f.set(0, 0, 0);
      int n = (drawType == JmolConstants.DRAW_ARC ? 2 :vertexCount);
      for (int i = 0; i < n; i++)
        pt1f.add(vertices[i]);
      pt1f.scale(1f / n);
      viewer.transformPoint(pt1f, pt1i);
      diameter = viewer.scaleToScreen(pt1i.z, (int) (width * 1000));
      if (diameter == 0)
        diameter = 1;
    }   
    if ((dmesh.isVector) && dmesh.haveXyPoints) {
      int ptXY = 0;
      // [x y] or [x,y] refers to an xy point on the screen
      // just a Point3f with z = Float.MAX_VALUE
      //  [x y %] or [x,y %] refers to an xy point on the screen
      // as a percent
      // just a Point3f with z = -Float.MAX_VALUE
      for (int i = 0; i < 2; i++)
        if (vertices[i].z == Float.MAX_VALUE || vertices[i].z == -Float.MAX_VALUE)
          ptXY += i + 1;
      if (--ptXY < 2) {
        renderXyArrow(ptXY);
        return;
      }
    }   
    int tension = 5;
    switch (drawType) {
    default:
      super.render2(false);
      break;
    case JmolConstants.DRAW_CIRCULARPLANE:
      if (dmesh.scale > 0)
        width *= dmesh.scale;
      super.render2(false);
      break;
    case JmolConstants.DRAW_CIRCLE:
      viewer.transformPoint(vertices[0], pt1i);
      if (diameter == 0 && width == 0)
        width = 1.0f;
      if (dmesh.scale > 0)
        width *= dmesh.scale;
      if (width > 0)
        diameter = viewer.scaleToScreen(pt1i.z, (int) (width * 1000));
      if (diameter > 0 && (mesh.drawTriangles || mesh.fillTriangles))
        g3d.drawFilledCircle(colix, mesh.fillTriangles ? colix : 0, diameter, pt1i.x, pt1i.y, pt1i.z);
      break;
    case JmolConstants.DRAW_CURVE:
    case JmolConstants.DRAW_LINE_SEGMENT:
      //unnecessary
      break;
    case JmolConstants.DRAW_ARC:
      //renderArrowHead(controlHermites[nHermites - 2], controlHermites[nHermites - 1], false);
      //
      // {pt1} {pt2} {ptref} {nDegreesOffset, theta, fractionalOffset}
      float nDegreesOffset = (vertexCount > 3 ? vertices[3].x : 0);
      float theta = (vertexCount > 3 ? vertices[3].y : 360);
      if (theta == 0)
        return;
      float fractionalOffset = (vertexCount > 3 ? vertices[3].z : 0);
      vTemp.set(vertices[1]);
      vTemp.sub(vertices[0]);
      // crossing point
      pt1f.scaleAdd(fractionalOffset, vTemp, vertices[0]);
      // define rotational axis
      Matrix3f mat = new Matrix3f();
      mat.set(new AxisAngle4f(vTemp, (float) (nDegreesOffset * Math.PI / 180)));
      // vector to rotate
      if (vertexCount > 2)
        vTemp2.set(vertices[2]);
      else
        vTemp2.set(Draw.randomPoint());
      vTemp2.sub(vertices[0]);
      vTemp2.cross(vTemp, vTemp2);
      vTemp2.cross(vTemp2, vTemp);
      vTemp2.normalize();
      vTemp2.scale(dmesh.scale / 2);
      mat.transform(vTemp2);
      //control points
      float degrees = theta / 5;
      while (Math.abs(degrees) > 5)
        degrees /= 2;
      nPoints = (int) (theta / degrees + 0.5f) + 1;
      while (nPoints < 10) {
        degrees /= 2;
        nPoints = (int) (theta / degrees + 0.5f) + 1;
      }
      mat.set(new AxisAngle4f(vTemp, (float) (degrees * Math.PI / 180)));
      screens = viewer.allocTempScreens(nPoints);
      int iBase = nPoints - (dmesh.scale < 2 ? 3 : 3);
      for (int i = 0; i < nPoints; i++) {
        if (i == iBase)
          vpt0.set(vpt1);
        vpt1.scaleAdd(1, vTemp2, pt1f);
        if (i == 0)
          vpt2.set(vpt1);
        viewer.transformPoint(vpt1, screens[i]);
        mat.transform(vTemp2);
      }
      if (dmesh.isVector && !dmesh.nohead) {
        renderArrowHead(vpt0, vpt1, 0.3f, false, false);
        viewer.transformPoint(pt1f, screens[nPoints - 1]);
      }
      pt1f.set(vpt2);
      break;
    case JmolConstants.DRAW_ARROW:
      if (vertexCount == 2) {
        renderArrowHead(vertices[0], vertices[1], 0, false, true);
        return;
      }
      int nHermites = 5;
      if (controlHermites == null || controlHermites.length < nHermites + 1) {
        controlHermites = new Point3f[nHermites + 1];
      }
      Graphics3D.getHermiteList(tension, vertices[vertexCount - 3],
            vertices[vertexCount - 2], vertices[vertexCount - 1],
            vertices[vertexCount - 1], vertices[vertexCount - 1],
            controlHermites, 0, nHermites);
      renderArrowHead(controlHermites[nHermites - 2], controlHermites[nHermites - 1], 0, false, false);
      break;
    }
    if (diameter == 0)
      diameter = 3;
    if (isCurved) {
      for (int i = 0, i0 = 0; i < nPoints - 1; i++) {
        g3d.fillHermite(tension, diameter, diameter, diameter, screens[i0],
            screens[i], screens[i + 1], screens[i
                + (i == nPoints - 2 ? 1 : 2)]);
        i0 = i;
      }
    } else if (isSegments) {
      for (int i = 0; i < nPoints - 1; i++)
        drawLine(i, i + 1, true, vertices[i], vertices[i + 1], screens[i], screens[i + 1]);
    }
   
    if (isDrawPickMode && !isExport) {
      renderHandles();
    }
  }
 
  private void drawLineData(List lineData) {
    if (diameter == 0)
      diameter = 3;
    for (int i = lineData.size(); --i >= 0;) {
      Point3f[] pts = (Point3f[]) lineData.get(i);
      viewer.transformPoint(pts[0], pt1i);
      viewer.transformPoint(pts[1], pt2i);
      drawLine(-1, -2, true, pts[0], pts[1], pt1i, pt2i);
    }
  }

  private void renderXyArrow(int ptXY) {
    int ptXYZ = 1 - ptXY;
    Point3f[] arrowPt = new Point3f[2];
    arrowPt[ptXYZ] = vpt1;
    arrowPt[ptXY] = vpt0;
    // set up (0,0,0) to ptXYZ in real and screen coordinates
    vpt0.set(screens[ptXY].x, screens[ptXY].y, screens[ptXY].z);
    viewer.rotatePoint(vertices[ptXYZ], vpt1);
    vpt1.z *= -1;
    float zoomDimension = viewer.getScreenDim();
    float scaleFactor = zoomDimension / 20f;
    vpt1.scaleAdd(dmesh.scale * scaleFactor, vpt1, vpt0);
    if (diameter == 0)
      diameter = 1;
    pt1i.set((int) vpt0.x, (int) vpt0.y, (int) vpt0.z );
    pt2i.set((int) vpt1.x, (int) vpt1.y, (int) vpt1.z );
    if (diameter < 0)
      g3d.drawDottedLine(pt1i, pt2i);
    else
      g3d.fillCylinder(Graphics3D.ENDCAPS_FLAT, diameter, pt1i, pt2i);
    renderArrowHead(vpt0, vpt1, 0, true, false);
  }

  private final Point3f pt0f = new Point3f();
  private final Point3i pt0i = new Point3i();

  private void renderArrowHead(Point3f pt1, Point3f pt2, float factor2,
                               boolean isTransformed, boolean withShaft) {
    if (dmesh.nohead)
      return;
    float fScale = dmesh.drawArrowScale;
    if (fScale == 0)
      fScale = viewer.getDefaultDrawArrowScale();
    if (fScale <= 0)
      fScale = 0.5f;
    if (isTransformed)
      fScale *= 40;
    if (factor2 > 0)
      fScale *= factor2;
   
    pt0f.set(pt1);
    pt2f.set(pt2);
    float d = pt0f.distance(pt2f);
    if (d == 0)
      return;
    vTemp.set(pt2f);
    vTemp.sub(pt0f);
    vTemp.normalize();
    vTemp.scale(fScale / 5);
    if (!withShaft)
      pt2f.add(vTemp);
    vTemp.scale(5);
    pt1f.set(pt2f);
    pt1f.sub(vTemp);
    if (isTransformed) {
      pt1i.set((int)pt1f.x, (int)pt1f.y, (int)pt1f.z);
      pt2i.set((int)pt2f.x, (int)pt2f.y, (int)pt2f.z);
    } else {
      viewer.transformPoint(pt2f, pt2i);
      viewer.transformPoint(pt1f, pt1i);
      viewer.transformPoint(pt0f, pt0i);
    }
    if (pt2i.z == 1 || pt1i.z == 1) //slabbed
      return;
    int headDiameter;
    if (diameter > 0) {
      headDiameter = diameter * 3;
    } else {
      vTemp.set(pt2i.x - pt1i.x, pt2i.y - pt1i.y, pt2i.z - pt1i.z);
      headDiameter = (int) (vTemp.length() * .5);
      diameter = headDiameter / 5;
    }
    if (diameter < 1)
      diameter = 1;
    if (headDiameter > 2)
      g3d.fillConeScreen(Graphics3D.ENDCAPS_FLAT, headDiameter, pt1i, pt2i);
    if (withShaft)
      g3d.fillCylinderScreen(Graphics3D.ENDCAPS_OPENEND, diameter, pt0i,
           pt1i);
  }
 
  private void renderHandles() {
    int diameter = (int) (10 * imageFontScaling);
    switch (drawType) {
    case JmolConstants.DRAW_NONE:
    case JmolConstants.DRAW_TRIANGLE:
      return;
    default:
      short colixFill = Graphics3D.getColixTranslucent(Graphics3D.GOLD, true, 0.5f);
      for (int i = dmesh.polygonCount; --i >= 0;) {
        if (!isPolygonDisplayable(i))
          continue;
        int[] vertexIndexes = dmesh.polygonIndexes[i];
        if (vertexIndexes == null)
          continue;
        for (int j = vertexIndexes.length; --j >= 0;) {
          int k = vertexIndexes[j];
          g3d.drawFilledCircle(Graphics3D.GOLD, colixFill, diameter, screens[k].x,
              screens[k].y, screens[k].z);
        }
        break;
      }
    }
  }
 
  private void renderInfo() {
    if (mesh.title == null || viewer.getDrawHover()
        || !g3d.setColix(viewer.getColixBackgroundContrast()))
      return;
    for (int i = dmesh.polygonCount; --i >= 0;)
      if (isPolygonDisplayable(i)) {
        //just the first line of the title -- nothing fancy here.
        byte fid = g3d.getFontFid(14 * imageFontScaling);
        g3d.setFont(fid);
        String s = mesh.title[i < mesh.title.length ? i : mesh.title.length - 1];
        int pt = 0;
        if (s.length() > 1 && s.charAt(0) == '>') {
          pt = dmesh.polygonIndexes[i].length - 1;
          s = s.substring(1);
          if (drawType == JmolConstants.DRAW_ARC)
            pt1f.set(pt2f);
        }
        if (drawType != JmolConstants.DRAW_ARC)
          pt1f.set(vertices[dmesh.polygonIndexes[i][pt]]);
        viewer.transformPoint(pt1f, pt1i);
        int offset = (int) (5 * imageFontScaling);
        g3d.drawString(s, null, pt1i.x + offset, pt1i.y - offset,
            pt1i.z, pt1i.z);
        break;
      }
  }
 
}
TOP

Related Classes of org.jmol.shapespecial.DrawRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.