Package org.jmol.shape

Source Code of org.jmol.shape.SticksRenderer

/* $RCSfile$
* $Author: hansonr $
* $Date: 2010-09-16 13:40:57 +0200 (jeu., 16 sept. 2010) $
* $Revision: 14310 $

*
* Copyright (C) 2002-2005  The Jmol Development Team
*
* Contact: jmol-developers@lists.sf.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.shape;

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

import org.jmol.api.JmolEdge;
import org.jmol.g3d.*;
import org.jmol.modelset.Atom;
import org.jmol.modelset.Bond;
import org.jmol.viewer.JmolConstants;

public class SticksRenderer extends ShapeRenderer {

  private boolean showMultipleBonds;
  private float multipleBondSpacing;
  private float multipleBondRadiusFactor;
  private byte modeMultipleBond;
  //boolean showHydrogens;
  private byte endcaps;

  private boolean ssbondsBackbone;
  private boolean hbondsBackbone;
  private boolean bondsBackbone;
  private boolean hbondsSolid;
 
  private Atom atomA, atomB;
  private Bond bond;
  private int xA, yA, zA;
  private int xB, yB, zB;
  private int dx, dy;
  private int mag2d;
  private short colixA, colixB;
  private int width;
  private boolean lineBond;
  private int bondOrder;
  private boolean renderWireframe;
  private boolean isAntialiased;
  private boolean slabbing;
  private boolean slabByAtom;

  protected void render() {
    slabbing = viewer.getSlabEnabled();
    slabByAtom = viewer.getSlabByAtom();         
    endcaps = Graphics3D.ENDCAPS_SPHERICAL;
    multipleBondSpacing = viewer.getMultipleBondSpacing();
    multipleBondRadiusFactor = viewer.getMultipleBondRadiusFactor();
    if (multipleBondSpacing > 0) {
      z = new Vector3f();
      x = new Vector3f();
      y = new Vector3f();
      p1 = new Point3f();
      p2 = new Point3f();
      s1 = new Point3i();
      s2 = new Point3i();
    }
    showMultipleBonds = multipleBondSpacing != 0 && viewer.getShowMultipleBonds();
    modeMultipleBond = viewer.getModeMultipleBond();
    renderWireframe = viewer.getInMotion() && viewer.getWireframeRotation();
    ssbondsBackbone = viewer.getSsbondsBackbone();
    hbondsBackbone = viewer.getHbondsBackbone();
    bondsBackbone = hbondsBackbone | ssbondsBackbone;
    hbondsSolid = viewer.getHbondsSolid();
    isAntialiased = g3d.isAntialiased();
    Bond[] bonds = modelSet.getBonds();
    for (int i = modelSet.getBondCount(); --i >= 0; ) {
      bond = bonds[i];
      if ((bond.getShapeVisibilityFlags() & myVisibilityFlag) != 0)
        renderBond();
    }
  }

  private void renderBond() {
    atomA = bond.getAtom1();
    atomB = bond.getAtom2();
    int order = bond.getOrder() & ~JmolEdge.BOND_NEW;
    if (bondsBackbone) {
      if (ssbondsBackbone && (order & JmolEdge.BOND_SULFUR_MASK) != 0) {
        // for ssbonds, always render the sidechain,
        // then render the backbone version
        /*
         mth 2004 04 26
         No, we are not going to do this any more
         render(bond, atomA, atomB);
         */

        atomA = atomA.getGroup().getLeadAtom(atomA);
        atomB = atomB.getGroup().getLeadAtom(atomB);
      } else if (hbondsBackbone
          && (order & JmolEdge.BOND_HYDROGEN_MASK) != 0) {
        atomA = atomA.getGroup().getLeadAtom(atomA);
        atomB = atomB.getGroup().getLeadAtom(atomB);
      }
    }
    if (!atomA.isInFrame() || !atomB.isInFrame()
        || !g3d.isInDisplayRange(atomA.screenX, atomA.screenY)
        || !g3d.isInDisplayRange(atomB.screenX, atomB.screenY)
        || modelSet.isAtomHidden(atomA.getIndex())
        || modelSet.isAtomHidden(atomB.getIndex()))
      return;

    if (slabbing) {
      if (g3d.isClippedZ(atomA.screenZ) && g3d.isClippedZ(atomB.screenZ))
        return;
      if(slabByAtom &&
          (g3d.isClippedZ(atomA.screenZ) || g3d.isClippedZ(atomB.screenZ)))
        return;         
    }
    colixA = atomA.getColix();
    colixB = atomB.getColix();
    if (((colix = bond.getColix()) & Graphics3D.OPAQUE_MASK) == Graphics3D.USE_PALETTE) {
      colix = (short) (colix & ~Graphics3D.OPAQUE_MASK);
      colixA = Graphics3D.getColixInherited((short) (colix | viewer
          .getColixAtomPalette(atomA, JmolConstants.PALETTE_CPK)), colixA);
      colixB = Graphics3D.getColixInherited((short) (colix | viewer
          .getColixAtomPalette(atomB, JmolConstants.PALETTE_CPK)), colixB);
    } else {
      colixA = Graphics3D.getColixInherited(colix, colixA);
      colixB = Graphics3D.getColixInherited(colix, colixB);
    }
    xA = atomA.screenX;
    yA = atomA.screenY;
    zA = atomA.screenZ;
    xB = atomB.screenX;
    yB = atomB.screenY;
    zB = atomB.screenZ;
    if (zA == 1 || zB == 1)
      return;
   
    // set the rendered bond order
   
    bondOrder = order & ~JmolEdge.BOND_NEW;
    if ((bondOrder & JmolEdge.BOND_PARTIAL_MASK) == 0) {
      if ((bondOrder & JmolEdge.BOND_SULFUR_MASK) != 0)
        bondOrder &= ~JmolEdge.BOND_SULFUR_MASK;
      if ((bondOrder & JmolEdge.BOND_COVALENT_MASK) != 0) {
        if (!showMultipleBonds
            || modeMultipleBond == JmolConstants.MULTIBOND_NEVER
            || (modeMultipleBond == JmolConstants.MULTIBOND_NOTSMALL && mad > JmolConstants.madMultipleBondSmallMaximum)) {
          bondOrder = 1;
        }
      }
    }
   
    // set the mask
   
    int mask = 0;
    switch (bondOrder) {
    case 1:
    case 2:
    case 3:
    case 4:
      break;
    case JmolEdge.BOND_ORDER_UNSPECIFIED:
    case JmolEdge.BOND_AROMATIC_SINGLE:
      bondOrder = 1;
      mask = (order == JmolEdge.BOND_AROMATIC_SINGLE ? 0 : 1);
      break;
    case JmolEdge.BOND_AROMATIC:
    case JmolEdge.BOND_AROMATIC_DOUBLE:
      bondOrder = 2;
      mask = (order == JmolEdge.BOND_AROMATIC ? getAromaticDottedBondMask()
          : 0);
      break;
    default:
      if ((bondOrder & JmolEdge.BOND_PARTIAL_MASK) != 0) {
        bondOrder = JmolConstants.getPartialBondOrder(order);
        mask = JmolConstants.getPartialBondDotted(order);
      } else if ((bondOrder & JmolEdge.BOND_HYDROGEN_MASK) != 0) {
        bondOrder = 1;
        if (!hbondsSolid)
          mask = -1;
      } else if (bondOrder == JmolEdge.BOND_STRUT) {
        bondOrder = 1;
      }
    }
   
    // set the diameter
   
    mad = bond.getMad();
    if (multipleBondRadiusFactor > 0 && bondOrder > 1)
      mad *= multipleBondRadiusFactor;
    dx = xB - xA;
    dy = yB - yA;
    width = viewer.scaleToScreen((zA + zB) / 2, mad);
    if (renderWireframe && width > 0)
      width = 1;
    lineBond = (width <= 1);
    if (lineBond && (isAntialiased)) {
      width = 3;
      lineBond = false;
    }
   
    // draw the bond
   
    switch (mask) {
    case -1:
      renderHbondDashed();
      break;
    default:
      drawBond(mask);
      break;
    }
  }
   
  private Vector3f x, y, z;
  private Point3f p1, p2;
  private Point3i s1, s2;
 
  private void drawBond(int dottedMask) {
    if (exportType == Graphics3D.EXPORT_CARTESIAN && bondOrder == 1) {
      // bypass screen rendering and just use the atoms themselves
      g3d.drawBond(atomA, atomB, colixA, colixB, endcaps, mad);
      return;
    }
    boolean isEndOn = (dx == 0 && dy == 0);
    if (isEndOn && lineBond)
      return;
    boolean doFixedSpacing = (bondOrder > 1
        && multipleBondSpacing > 0
        && (viewer.getHybridizationAndAxes(atomA.index, z, x, "pz") != null
            || viewer.getHybridizationAndAxes(atomB.index, z, x, "pz") != null)
        && !Float.isNaN(x.x));
    if (isEndOn && !doFixedSpacing) {
      // end-on view
      int space = width / 8 + 3;
      int step = width + space;
      int y = yA - (bondOrder - 1) * step / 2;
      do {
        fillCylinder(colixA, colixA, endcaps, width, xA, y, zA, xA, y, zA);
        y += step;
      } while (--bondOrder > 0);
      return;
    }
    if (bondOrder == 1) {
      if ((dottedMask & 1) != 0)
        drawDashed(xA, yA, zA, xB, yB, zB);
      else
        fillCylinder(colixA, colixB, endcaps, width, xA, yA, zA, xB, yB, zB);
      return;
    }
    if (doFixedSpacing) {
      x.sub(atomB, atomA);
      y.cross(x, z);
      y.normalize();
      y.scale(multipleBondSpacing);
      x.set(y);
      x.scale((bondOrder - 1) / 2f);
      p1.sub(atomA, x);
      p2.sub(atomB, x);
      while (true) {
        viewer.transformPoint(p1, s1);
        viewer.transformPoint(p2, s2);
        p1.add(y);
        p2.add(y);
        if ((dottedMask & 1) != 0)
          drawDashed(s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
        else
          fillCylinder(colixA, colixB, endcaps, width, s1.x, s1.y, s1.z, s2.x,
              s2.y, s2.z);
        dottedMask >>= 1;
        if (--bondOrder <= 0)
          break;
        stepAxisCoordinates();
      }
      return;
    }
    int dxB = dx * dx;
    int dyB = dy * dy;
    mag2d = (int) (Math.sqrt(dxB + dyB) + 0.5);
    resetAxisCoordinates();
    while (true) {
      if ((dottedMask & 1) != 0)
        drawDashed(xAxis1, yAxis1, zA, xAxis2, yAxis2, zB);
      else
        fillCylinder(colixA, colixB, endcaps, width, xAxis1, yAxis1, zA,
            xAxis2, yAxis2, zB);
      dottedMask >>= 1;
      if (--bondOrder <= 0)
        break;
      stepAxisCoordinates();
    }
  }

  private int xAxis1, yAxis1, xAxis2, yAxis2, dxStep, dyStep;

  private void resetAxisCoordinates() {
    int space = mag2d >> 3;
    if (multipleBondSpacing != -1 && multipleBondSpacing < 0)
      space *= -multipleBondSpacing;
    int step = width + space;
    dxStep = step * dy / mag2d;
    dyStep = step * -dx / mag2d;
    xAxis1 = xA;
    yAxis1 = yA;
    xAxis2 = xB;
    yAxis2 = yB;
    int f = (bondOrder - 1);
    xAxis1 -= dxStep * f / 2;
    yAxis1 -= dyStep * f / 2;
    xAxis2 -= dxStep * f / 2;
    yAxis2 -= dyStep * f / 2;
  }

  private void stepAxisCoordinates() {
    xAxis1 += dxStep; yAxis1 += dyStep;
    xAxis2 += dxStep; yAxis2 += dyStep;
  }

  private int getAromaticDottedBondMask() {
    Atom atomC = atomB.findAromaticNeighbor(atomA.getIndex());
    if (atomC == null)
      return 1;
    int dxAC = atomC.screenX - xA;
    int dyAC = atomC.screenY - yA;
    return ((dx * dyAC - dy * dxAC) < 0 ? 2 : 1);
  }

  private void drawDashed(int xA, int yA, int zA, int xB, int yB, int zB) {
    int dx = xB - xA;
    int dy = yB - yA;
    int dz = zB - zA;
    int i = 2;
    while (i <= 9) {
      int xS = xA + (dx * i) / 12;
      int yS = yA + (dy * i) / 12;
      int zS = zA + (dz * i) / 12;
      i += 3;
      int xE = xA + (dx * i) / 12;
      int yE = yA + (dy * i) / 12;
      int zE = zA + (dz * i) / 12;
      i += 2;
      fillCylinder(colixA, colixB, Graphics3D.ENDCAPS_FLAT, width,
                         xS, yS, zS, xE, yE, zE);
    }
  }

  private void renderHbondDashed() {
    int dx = xB - xA;
    int dy = yB - yA;
    int dz = zB - zA;
    int i = 1;
    while (i < 10) {
      int xS = xA + (dx * i) / 10;
      int yS = yA + (dy * i) / 10;
      int zS = zA + (dz * i) / 10;
      short colixS = i < 5 ? colixA : colixB;
      i += 2;
      int xE = xA + (dx * i) / 10;
      int yE = yA + (dy * i) / 10;
      int zE = zA + (dz * i) / 10;
      short colixE = i < 5 ? colixA : colixB;
      ++i;
      fillCylinder(colixS, colixE, Graphics3D.ENDCAPS_FLAT, width,
                         xS, yS, zS, xE, yE, zE);
    }
  }
   
  private void fillCylinder(short colixA, short colixB, byte endcaps,
                              int diameter, int xA, int yA, int zA, int xB,
                              int yB, int zB) {
    if (lineBond)
      g3d.drawLine(colixA, colixB, xA, yA, zA, xB, yB, zB);
    else
      g3d.fillCylinder(colixA, colixB, endcaps,
          (exportType == Graphics3D.EXPORT_NOT || mad == 1 ? diameter : mad),
          xA, yA, zA, xB, yB, zB);
  }

}
TOP

Related Classes of org.jmol.shape.SticksRenderer

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.