Package org.jmol.util
Class MeshCapper
- java.lang.Object
-
- org.jmol.util.MeshCapper
-
public class MeshCapper extends java.lang.Object
A class to properly cap a convoluted, closed slice of an isosurface inspired by: Computational Geometry: Algorithms and Applications Mark de Berg, Marc van Kreveld, Mark Overmars, and Otfried Schwarzkopf Springer-Verlag, Berlin Heidelberg 1997 Chapter 3. Polygon Triangulation Thanks given to Olaf Hall-Holt for pointing me to this reference. Extensively modified: - quaternion transform from 3D plane to XY plane for best precision - using directional edges -- no angle measurements necessary - continuous splitting off of triangles - independent dynamic monotonic regions created and processed as one stream - no need for vertex typing - no push/pop stacks INPUT: stream of [a b] ordered-vertex edges such that triangle a-b-c is interior if (ab.cross.ac).dot.planeNormal > 0 (right-hand rule; counter-clockwise edge flow) Bob Hanson - Jan 11, 2015- Author:
- Bob Hanson, hansonr@stolaf.edu
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private class
MeshCapper.CapVertex
A class to provide linked vertices for MeshCapper
-
Field Summary
Fields Modifier and Type Field Description private static int
ASCENDER
private java.util.Map<java.lang.Integer,MeshCapper.CapVertex>
capMap
initialization onlyprivate static int
DESCENDER
private boolean
dumping
for debuggingprivate static int
LAST
private javajs.util.Lst<MeshCapper.CapVertex[]>
lstRegions
dynamic region processing.private javajs.util.Lst<int[]>
lstTriangles
private int
nPoints
private int
nRegions
informational onlyprivate int
nTriangles
informational onlyprivate MeshSlicer
slicer
source of edges; consumer of trianglesprivate javajs.util.Lst<MeshCapper.CapVertex>
vertices
-
Constructor Summary
Constructors Constructor Description MeshCapper()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description (package private) void
addEdge(int ipt1, int ipt2, int thisSet)
Input method from MeshSlicer.private MeshCapper.CapVertex
addPoint(int thisSet, int i)
The MeshSlicer class manages all introduction of vertices; we must pass on to it the subset of vertices from the original Jmol isosurface being capped.private void
addTriangle(MeshCapper.CapVertex v0, MeshCapper.CapVertex v1, MeshCapper.CapVertex v2, java.lang.String note)
Add the triangle and remove v1 from the chain.private boolean
checkWinding(MeshCapper.CapVertex v0, MeshCapper.CapVertex v1, MeshCapper.CapVertex v2)
Check for CCW winding.(package private) void
clear()
private static void
clearV(MeshCapper.CapVertex v)
(package private) void
createCap(javajs.util.V3 norm)
Entry point when finished generating edges.private void
drawTriangle(int index, MeshCapper.CapVertex v0, MeshCapper.CapVertex v1, MeshCapper.CapVertex v2, java.lang.String color)
for debuggingprivate javajs.util.T3
getInputPoint(MeshCapper.CapVertex v)
for debuggingprivate MeshCapper.CapVertex
getLastPoint(MeshCapper.CapVertex v)
Find the lowest ascender or descender above scan line bounding the region for this point.private boolean
isEdge(int i, int j)
private void
newRegion(MeshCapper.CapVertex v)
Add a new region to the list of regions.private void
outputTriangle(int ipt1, int ipt2, int ipt3)
Export triangle to MeshSlicerprivate MeshCapper.CapVertex
process(MeshCapper.CapVertex v)
Handle the point; mark as processed.private void
processMonotonic(MeshCapper.CapVertex v, boolean isDescending)
Process a standard monotonic region, cleaving off as many triangles as possible.private MeshCapper.CapVertex
processSplit(MeshCapper.CapVertex v, MeshCapper.CapVertex last)
Process what M3O refer to as a "split" vertex, which we handle differently here, cloning the "helper" point and the "split" point, creating a new region if necessary, and then swapping pointers.MeshCapper
set(MeshSlicer slicer)
private MeshCapper.CapVertex[]
test(MeshCapper.CapVertex[] vs)
int[][]
triangulateFaces(int[][] faces, javajs.util.P3[] vertices, int[][] faceTriangles)
generic entry for a set of facesint[][]
triangulatePolygon(javajs.util.P3[] points, int nPoints)
generic entry for a polygon
-
-
-
Field Detail
-
slicer
private MeshSlicer slicer
source of edges; consumer of triangles
-
dumping
private boolean dumping
for debugging
-
capMap
private java.util.Map<java.lang.Integer,MeshCapper.CapVertex> capMap
initialization only
-
vertices
private javajs.util.Lst<MeshCapper.CapVertex> vertices
-
lstRegions
private javajs.util.Lst<MeshCapper.CapVertex[]> lstRegions
dynamic region processing. These are just [DESCENDER, ASCENDER, LAST] for each region
-
DESCENDER
private static final int DESCENDER
- See Also:
- Constant Field Values
-
ASCENDER
private static final int ASCENDER
- See Also:
- Constant Field Values
-
LAST
private static final int LAST
- See Also:
- Constant Field Values
-
nTriangles
private int nTriangles
informational only
-
nRegions
private int nRegions
informational only
-
lstTriangles
private javajs.util.Lst<int[]> lstTriangles
-
nPoints
private int nPoints
-
-
Method Detail
-
set
public MeshCapper set(MeshSlicer slicer)
- Parameters:
slicer
-- Returns:
- this
-
clear
void clear()
-
triangulateFaces
public int[][] triangulateFaces(int[][] faces, javajs.util.P3[] vertices, int[][] faceTriangles)
generic entry for a set of faces- Parameters:
faces
- array of pointers into pointsvertices
-faceTriangles
-- Returns:
- array of triangles [a b c mask]
-
triangulatePolygon
public int[][] triangulatePolygon(javajs.util.P3[] points, int nPoints)
generic entry for a polygon- Parameters:
points
-nPoints
- number of points or -1- Returns:
- int[][i j k mask]
-
addEdge
void addEdge(int ipt1, int ipt2, int thisSet)
Input method from MeshSlicer. Pointers are into MeshSlicer.m.vs[]- Parameters:
ipt1
-ipt2
-thisSet
-
-
addPoint
private MeshCapper.CapVertex addPoint(int thisSet, int i)
The MeshSlicer class manages all introduction of vertices; we must pass on to it the subset of vertices from the original Jmol isosurface being capped.- Parameters:
thisSet
-i
-- Returns:
- a CapVertex pointing to this new point in the isosurface or one we already have
-
getInputPoint
private javajs.util.T3 getInputPoint(MeshCapper.CapVertex v)
for debugging- Parameters:
v
-- Returns:
- external point or test point
-
outputTriangle
private void outputTriangle(int ipt1, int ipt2, int ipt3)
Export triangle to MeshSlicer- Parameters:
ipt1
-ipt2
-ipt3
-
-
isEdge
private boolean isEdge(int i, int j)
-
test
private MeshCapper.CapVertex[] test(MeshCapper.CapVertex[] vs)
-
createCap
void createCap(javajs.util.V3 norm)
Entry point when finished generating edges.- Parameters:
norm
-
-
process
private MeshCapper.CapVertex process(MeshCapper.CapVertex v)
Handle the point; mark as processed.- Parameters:
v
-- Returns:
- next point to process
-
clearV
private static void clearV(MeshCapper.CapVertex v)
-
processMonotonic
private void processMonotonic(MeshCapper.CapVertex v, boolean isDescending)
Process a standard monotonic region, cleaving off as many triangles as possible.- Parameters:
v
-isDescending
-
-
processSplit
private MeshCapper.CapVertex processSplit(MeshCapper.CapVertex v, MeshCapper.CapVertex last)
Process what M3O refer to as a "split" vertex, which we handle differently here, cloning the "helper" point and the "split" point, creating a new region if necessary, and then swapping pointers.- Parameters:
v
-last
- "helper" or left edge- Returns:
- new point clone of this
-
newRegion
private void newRegion(MeshCapper.CapVertex v)
Add a new region to the list of regions.- Parameters:
v
-
-
getLastPoint
private MeshCapper.CapVertex getLastPoint(MeshCapper.CapVertex v)
Find the lowest ascender or descender above scan line bounding the region for this point. In the case of a region that consists of a single edge with descender above ascender, this will return the ascender. In the case where there are two independent regions, it is possible for the lowest to be missed, but to no import. [This is MOST confusing in the M3O book.]- Parameters:
v
-- Returns:
- pt
-
checkWinding
private boolean checkWinding(MeshCapper.CapVertex v0, MeshCapper.CapVertex v1, MeshCapper.CapVertex v2)
Check for CCW winding.- Parameters:
v0
-v1
-v2
-- Returns:
- true if properly wound -- (v1-v0).cross.(v2-v0).dot.norm > 0
-
addTriangle
private void addTriangle(MeshCapper.CapVertex v0, MeshCapper.CapVertex v1, MeshCapper.CapVertex v2, java.lang.String note)
Add the triangle and remove v1 from the chain.- Parameters:
v0
-v1
-v2
-note
-
-
drawTriangle
private void drawTriangle(int index, MeshCapper.CapVertex v0, MeshCapper.CapVertex v1, MeshCapper.CapVertex v2, java.lang.String color)
for debugging- Parameters:
index
-v0
-v1
-v2
-color
-
-
-