Package org.jmol.util

Source Code of org.jmol.util.MeshSurface

package org.jmol.util;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

import javax.vecmath.Point3f;
import javax.vecmath.Point4f;
import javax.vecmath.Vector3f;

import org.jmol.g3d.Graphics3D;
import org.jmol.modelset.BoxInfo;

public class MeshSurface {

  protected static final int SEED_COUNT = 25;
  public boolean haveQuads;
  public short colix;
  public boolean isColorSolid = true;
  public int vertexCount;
  public Point3f[] vertices;
  public Point3f[] offsetVertices;
  public short[] vertexColixes;
  public int polygonCount;
  public int[][] polygonIndexes;
  public short[] polygonColixes;
  public Vector3f[] vertexNormals;
  public BitSet bsFaces;
  public Point3f ptOffset;
  public float scale3d;

  public MeshSurface() {
  }

  public void setColix(short colix) {
    this.colix = colix;
  }

  public int addVertexCopy(Point3f vertex) { //used by mps and surfaceGenerator
    if (vertexCount == 0)
      vertices = new Point3f[SEED_COUNT];
    else if (vertexCount == vertices.length)
      vertices = (Point3f[]) ArrayUtil.doubleLength(vertices);
    vertices[vertexCount] = new Point3f(vertex);
    return vertexCount++;
  }

  public void addTriangle(int vertexA, int vertexB, int vertexC) {
    addPolygon(new int[] { vertexA, vertexB, vertexC });
  }

  public void addQuad(int vertexA, int vertexB, int vertexC, int vertexD) {
    haveQuads = true;
    addPolygon(new int[] { vertexA, vertexB, vertexC, vertexD });
  }

  protected int addPolygon(int[] polygon) {
    int n = polygonCount;
    if (polygonCount == 0)
      polygonIndexes = new int[SEED_COUNT][];
    else if (polygonCount == polygonIndexes.length)
      polygonIndexes = (int[][]) ArrayUtil.doubleLength(polygonIndexes);
    polygonIndexes[polygonCount++] = polygon;
    return n;
  }

  public void setPolygonCount(int polygonCount) {   
    this.polygonCount = polygonCount;
    if (polygonCount < 0)
      return;
    if (polygonIndexes == null || polygonCount > polygonIndexes.length)
      polygonIndexes = new int[polygonCount][];
  }

  public float[] vertexValues;
  public BitSet[] surfaceSet;
  public int[] vertexSets;
  public int nSets = 0;
 
  public int addVertexCopy(Point3f vertex, float value) {
    if (vertexCount == 0)
      vertexValues = new float[SEED_COUNT];
    else if (vertexCount >= vertexValues.length)
      vertexValues = (float[]) ArrayUtil.doubleLength(vertexValues);
    vertexValues[vertexCount] = value;
    return addVertexCopy(vertex);
  }

  public int addTriangleCheck(int vertexA, int vertexB, int vertexC, int check,
                              int check2, int color) {
    return (vertices == null
        || vertexValues != null
        && (Float.isNaN(vertexValues[vertexA])
            || Float.isNaN(vertexValues[vertexB])
            || Float.isNaN(vertexValues[vertexC]))
        || Float.isNaN(vertices[vertexA].x)
        || Float.isNaN(vertices[vertexB].x)
        || Float.isNaN(vertices[vertexC].x)
        ? -1
      : addPolygon(new int[] { vertexA, vertexB, vertexC, check, check2 },
        color));
  }

  private int lastColor;
  private short lastColix;
   
  private int addPolygon(int[] polygon, int color) {
    if (color != 0) {
      if (polygonColixes == null || polygonCount == 0)
        lastColor = 0;
      short colix = (color == lastColor ? lastColix : (lastColix = Graphics3D
          .getColix(lastColor = color)));
      setPolygonColix(polygonCount, colix);
    }
    return addPolygon(polygon);
  }

  private void setPolygonColix(int index, short colix) {
    if (polygonColixes == null) {
      polygonColixes = new short[SEED_COUNT];
    } else if (index == polygonColixes.length) {
      polygonColixes = (short[]) ArrayUtil.doubleLength(polygonColixes);
    }
    polygonColixes[index] = colix;
  }
 
  public void invalidatePolygons() {
    for (int i = polygonCount; --i >= 0;)
      if (!setABC(i))
        polygonIndexes[i] = null;
  }

  protected int iA, iB, iC;
 
  protected boolean setABC(int i) {
    int[] vertexIndexes = polygonIndexes[i];
    return vertexIndexes != null
          && !(Float.isNaN(vertexValues[iA = vertexIndexes[0]])
            || Float.isNaN(vertexValues[iB = vertexIndexes[1]])
            || Float.isNaN(vertexValues[iC = vertexIndexes[2]]));
  }

  public void slabPolygons(Object slabbingObject, boolean andCap) {
    if (slabbingObject instanceof Point4f) {
      getIntersection((Point4f) slabbingObject, null, andCap);
      return;
    }
    if (slabbingObject instanceof Point3f[]) {
      Point4f[] faces = BoxInfo.getFacesFromCriticalPoints((Point3f[]) slabbingObject);
      for (int i = 0; i < faces.length; i++)
        getIntersection((Point4f) faces[i], null, andCap);
      return;
    }
  }

  public boolean getIntersection(Point4f plane, List vData, boolean andCap) {
    boolean isSlab = (vData == null);
    Point3f[] pts;
    int iD, iE;

    List iPts = (andCap ? new ArrayList() : null);
    for (int i = polygonIndexes.length; --i >= 0;) {
      if (!setABC(i))
        continue;
      Point3f vA, vB, vC;
      float d1 = Measure.distanceToPlane(plane, vA = vertices[iA]);
      float d2 = Measure.distanceToPlane(plane, vB = vertices[iB]);
      float d3 = Measure.distanceToPlane(plane, vC = vertices[iC]);
      int test1 = (d1 < 0 ? 1 : 0) + (d2 < 0 ? 2 : 0) + (d3 < 0 ? 4 : 0);
      int test2 = (d1 >= 0 ? 1 : 0) + (d2 >= 0 ? 2 : 0) + (d3 >= 0 ? 4 : 0);
      pts = null;
      switch (test1) {
      case 0:
      case 7:
        // all on the same side
        break;
      case 1:
      case 6:
        // BC on same side
        pts = new Point3f[] { interpolatePoint(vA, vB, -d1, d2),
            interpolatePoint(vA, vC, -d1, d3)};
        break;
      case 2:
      case 5:
        //AC on same side
        pts = new Point3f[] { interpolatePoint(vB, vA, -d2, d1),
            interpolatePoint(vB, vC, -d2, d3)};
        break;
      case 3:
      case 4:
        //AB on same side need A-C, B-C
        pts = new Point3f[] { interpolatePoint(vC, vA, -d3, d1),
            interpolatePoint(vC, vB, -d3, d2)};
        break;
      }
      if (isSlab) {
        iD = iE = 0;
        //             A
        //            / \
        //           B---C
        switch (test2) {
        case 0:
          // all on the same side
          continue;
        case 7:
          // all on the same side
          break;
        case 1:
          // BC on side to keep
          iD = addVertexCopy(pts[1], vertexValues[iA])//AC
          iE = addVertexCopy(pts[0], vertexValues[iA])//AB
          addTriangleCheck(iE, iB, iC, 0, 0, 0);
          addTriangleCheck(iE, iC, iD, 0, 0, 0);
          break;
        case 2:
          // AC on side to keep
          iD = addVertexCopy(pts[0], vertexValues[iB])//AB
          iE = addVertexCopy(pts[1], vertexValues[iB])//BC
          addTriangleCheck(iA, iD, iC, 0, 0, 0);
          addTriangleCheck(iD, iE, iC, 0, 0, 0);
          break;
        case 3:
          //AB on side to toss
          iD = addVertexCopy(pts[0], vertexValues[iA])//AC
          iE = addVertexCopy(pts[1], vertexValues[iB])//BC
          addTriangleCheck(iE, iC, iD, 0, 0, 0);
          break;
        case 4:
          //AB on side to keep
          iD = addVertexCopy(pts[1], vertexValues[iC])//BC
          iE = addVertexCopy(pts[0], vertexValues[iC])//AC
          addTriangleCheck(iA, iB, iE, 0, 0, 0);
          addTriangleCheck(iE, iB, iD, 0, 0, 0);
          break;
        case 5:
          //AC on side to toss
          iD = addVertexCopy(pts[1], vertexValues[iC])//BC
          iE = addVertexCopy(pts[0], vertexValues[iA])//AB
          addTriangleCheck(iE, iB, iD, 0, 0, 0);
          break;
        case 6:
          // BC on side to toss
          iD = addVertexCopy(pts[0], vertexValues[iB]); //AB
          iE = addVertexCopy(pts[1], vertexValues[iC]); //AC
          addTriangleCheck(iA, iD, iE, 0, 0, 0);
          break;
        }
        polygonIndexes[i] = null;
        if (andCap && iD > 0)
          iPts.add(new int[] {iD, iE});
      } else if (pts != null) {
        vData.add(pts);
      }
    }
    if (andCap && iPts.size() > 0) {
      Point3f center = new Point3f();
      for (int i = iPts.size(); --i >= 0;) {
        int[] ipts = (int[]) iPts.get(i);
        center.add(vertices[ipts[0]]);
        center.add(vertices[ipts[1]]);
      }
      center.scale(0.5f / iPts.size());
      int v0 = addVertexCopy(center);
      for (int i = iPts.size(); --i >= 0;) {
        int[] ipts = (int[]) iPts.get(i);
        iD = addVertexCopy(vertices[ipts[0]], vertexValues[ipts[0]]);
        iE = addVertexCopy(vertices[ipts[1]], vertexValues[ipts[1]]);
        addTriangleCheck(iD, v0, iE, 0, 0, 0);
      }
    }
    return false;
  }

  private static Point3f interpolatePoint(Point3f v1, Point3f v2, float d1, float d2) {
    float f = d1 / (d1 + d2);
    if (f < 0.0001)
      f = 0;
    else if (f > 0.9999)
      f = 1;
    return new Point3f(v1.x + (v2.x - v1.x) * f,
        v1.y + (v2.y - v1.y) * f,
        v1.z + (v2.z - v1.z) * f);   
  }
 
}
TOP

Related Classes of org.jmol.util.MeshSurface

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.