public class PolygonalMesh extends MeshBase
Modifier and Type | Field and Description |
---|---|
static int |
ALL_DEGENERACIES |
boolean |
canSelfIntersect |
static int |
computedFaceNormals |
static int |
ISOLATED_VERTICES |
static int |
NON_MANIFOLD_EDGES |
static int |
NON_MANIFOLD_VERTICES |
static int |
OPEN_EDGES |
XMeshToWorld
TRANSPARENT, TWO_DIMENSIONAL
Constructor and Description |
---|
PolygonalMesh()
Creates an empty polygonal mesh.
|
PolygonalMesh(java.io.File file)
Creates a polygonal mesh and initializes it from a file,
with the file format being inferred from the file name suffix.
|
PolygonalMesh(PolygonalMesh old) |
PolygonalMesh(java.lang.String fileName)
Creates a polygonal mesh and initializes it from a file,
with the file format being inferred from the file name suffix.
|
Modifier and Type | Method and Description |
---|---|
Face |
addFace(int[] indices)
Adds a face to this mesh.
|
Face |
addFace(int idx0,
int idx1,
int idx2)
Adds a triangular face to this mesh.
|
Face |
addFace(int idx0,
int idx1,
int idx2,
int idx3)
Adds a quad face to this mesh.
|
Face |
addFace(Vertex3d[] vertices)
Adds a face to this mesh.
|
Face |
addFace(Vertex3d v0,
Vertex3d v1,
Vertex3d v2)
Adds a triangular face to this mesh.
|
Face |
addFace(Vertex3d v0,
Vertex3d v1,
Vertex3d v2,
Vertex3d v3)
Adds a quad face to this mesh.
|
void |
addMesh(MeshBase mesh) |
void |
addMesh(PolygonalMesh mesh,
boolean respectTransforms)
Adds copies of the vertices and faces of another mesh to this mesh.
|
void |
autoGenerateNormals()
Computes vertex normals using an angle-weighted average of the normals
formed by the edges incident on each vertex.
|
void |
checkConsistency()
Make sure that this mesh is consistent, by checking that:
(1) vertex and face indices are consistent
(2) every face half edge is registered with it's head vertex
(3) every half edge's opposite, if non-null, points back to itself
(4) every half edge's head is the next half-edge's tail
(5) every half edge's face is valid
(6) every half edge's head and tail are different
(7) every vertex indicent half edge refers to a valid face
|
double |
checkFaceNormals() |
void |
checkForDegenerateFaces() |
void |
clear()
Clears this mesh (makes it empty).
|
void |
clearBVTree() |
void |
clearFaces() |
void |
clearHardEdges()
Clears all the hard edges currently in this mesh.
|
PolygonalMesh |
clone()
Creates a clone of this mesh.
|
double |
computeArea()
Computes the surface area of this mesh.
|
double |
computeAverageEdgeLength()
Computes the average edge length for this mesh.
|
double |
computeCentreOfVolume(Vector3d c)
Computes the centre of volume of the mesh
|
double |
computeInertia(SpatialInertia M,
double density)
Computes a spatial inertia for the volume defined by this mesh, assuming
a uniform density density.
|
RigidTransform3d |
computePrincipalAxes() |
static RigidTransform3d |
computePrincipalAxes(PolygonalMesh mesh) |
int[] |
computeVertexNormals(java.util.ArrayList<Vector3d> normals,
boolean multiNormals)
Computes a set of vertex normals for this mesh, using an
angle-weighted average of the normals formed by the edges incident on
each vertex.
|
double |
computeVolume()
Computes the volume of this mesh, on the assumption that it is manifold
and closed.
|
double |
computeVolumeIntegrals(Vector3d mov1,
Vector3d mov2,
Vector3d pov)
Computes the volume integrals of this mesh, on the assumption that it is
manifold and closed.
|
PolygonalMesh |
copy()
Creates a copy of this mesh.
|
int |
countBorders() |
int |
countConnected() |
int |
countEdges() |
double |
countGenus() |
SpatialInertia |
createInertia(double density)
Creates a spatial inertia for the volume defined by this mesh, assuming a
constant density.
|
SpatialInertia |
createInertia(double mass,
MassDistribution dist)
Computes a spatial inertia for this mesh, given a mass and a mass
distribution.
|
RenderProps |
createRenderProps(HasProperties host)
Creates an appropriate RenderProps for this Mesh.
|
int[] |
createVertexIndices()
Creates and returns the vertex indices associated with each geometric
feature in this mesh.
|
double |
distanceToPoint(Point3d pnt)
If this mesh is triangular, returns the nearest distance to a point.
|
double |
distanceToPoint(Point3d nearPnt,
Point3d pnt)
If this mesh is triangular, returns the nearest distance to a point.
|
int |
doMergeCloseVertices(double dsqr) |
boolean |
epsilonEquals(MeshBase base,
double eps)
Tests to see if a mesh equals this one.
|
int |
estimateMemoryUsage()
Returns the estimated memory useage for this mesh, in bytes.
|
void |
extendOpenEdges(double amount)
Extends the first open edge loop found.
|
boolean |
faceNormalsValid()
Returns true if face normals are currently valid.
|
java.util.ArrayList<HalfEdge> |
findBorderEdges() |
java.util.ArrayList<Face> |
findBorderFaces() |
java.util.ArrayList<Vertex3d> |
findNeighbouringVertices(Vertex3d vtx,
double dist)
Find all vertices in the neighbourhood of
vtx that are within a
distance dist of vtx . |
java.util.ArrayList<Vertex3d> |
findNonManifoldVertices() |
void |
flip() |
BVTree |
getBVTree()
Returns a bounding volume tree to be used for proximity queries
involving this mesh.
|
Face |
getFace(int idx)
Returns the face with a specified index
|
java.util.ArrayList<Face> |
getFaces()
Returns this mesh's faces.
|
HalfEdge |
getHalfEdge(int idx)
Returns the half-edge with a specified index.
|
boolean |
getMultipleAutoNormals()
Returns
true if multiple vertex normals are allowed when
normals are computed automatically. |
int |
getRenderHints()
Returns a bit code giving rendering hints about this renderable.
|
DistanceGrid |
getSignedDistanceGrid() |
DistanceGrid |
getSignedDistanceGrid(double margin,
Vector3i cellDivisions) |
PolygonalMesh |
getSubdivisionMesh()
Generates and returns a subdivided version of this mesh interpolated using
cubic patches.
|
int |
getSubdivisions() |
boolean |
getWriteNormals()
Returns
true if this mesh's normals should be written
to a file. |
boolean |
hasAutoNormalCreation()
Returns
true if this mesh automatically creates a default
set of normals if MeshBase.getNormals() is called and no normals have been
explicitly set using MeshBase.setNormals(java.util.List<maspack.matrix.Vector3d>, int[]) . |
boolean |
hasHardEdge(int vidx0,
int vidx1)
Returns
true if the edge between the vertices indexed by
vidx0 and vidx1 exists and is hard, as
described for hasHardEdge(v0,v1) . |
boolean |
hasHardEdge(Vertex3d v0,
Vertex3d v1)
Returns
true if the edge between vertices v0
and v1 exists and is hard. |
boolean |
hasIsolatedVertices()
Queries whether or not this mesh has isolated vertices.
|
boolean |
hasNonManifoldEdges()
Queries whether or not this mesh has non-manifold edges.
|
boolean |
hasNonManifoldVertices()
Queries whether or not this mesh has non-manifold vertices.
|
boolean |
hasOpenEdges()
Queries whether or not this mesh has open edges.
|
void |
interpolate(Point3d p,
Face f,
double u,
double v)
Smoothly interpolate a face using barycentric coordinates.
|
void |
inverseTransform(AffineTransform3dBase X)
Applies an inverse affine transformation to the vertices of this mesh.
|
void |
inverseTransform(VectorTransformer3d T)
Applies an inverse vector transformation to the vertices of this mesh.
|
boolean |
isBorderVertex(Vertex3d vtx) |
boolean |
isClosed()
Queries if this mesh is closed.
|
boolean |
isManifold()
Queries if this mesh is manifold.
|
boolean |
isQuad()
Returns true if this is a quad mesh.
|
boolean |
isTriangular()
Returns true if this mesh is triangular.
|
boolean |
isWatertight()
Queries if this mesh is watertight.
|
int |
mergeCloseVertices(double dist)
Merge vertices that are within a prescribed distance of each other.
|
boolean |
mergeCoplanarFaces(double cosLimit)
Merges adjacent faces whose normals satisfy n1.dot(n2)
> cosLimit |
Face |
nearestFaceToPoint(Point3d nearPnt,
Vector2d uv,
Point3d pnt)
If this mesh is triangular, returns the nearest triangular face to a
point.
|
void |
notifyVertexPositionsModified()
Notifies this mesh that vertex positions have been modified, and cached
data dependent on these positions should be invalidated.
|
int |
numDegenerateFaces() |
int |
numDisconnectedVertices() |
int |
numFaces()
Returns the number of faces in this mesh.
|
int |
numFeatures()
Returns the number of features in this mesh.
|
int |
numHardEdges()
Returns the number of hard edges currently in this mesh.
|
PolygonalMesh[] |
partitionIntoConnectedMeshes()
Copies this mesh into a set of connected meshes and returns these as an
array.
|
int |
pointIsInside(Point3d pnt)
If this mesh is triangular and closed, determines if a point is inside or
outside the mesh.
|
void |
prerender(RenderProps props) |
void |
printDegeneracies() |
void |
printDegeneracies(int printCode)
Prints topological degeneracies associated with this mesh.
|
void |
printDegenerateFaces() |
void |
read(java.io.Reader reader)
Reads the contents of this mesh from a Reader.
|
void |
read(ReaderTokenizer rtok,
boolean zeroIndexed)
Reads the contents of this mesh from a ReaderTokenizer.
|
void |
read(java.lang.String input)
Reads the contents of this mesh from a string.
|
void |
read(java.lang.String input,
boolean zeroIndexed)
Reads the contents of this mesh from a string.
|
int |
removeDisconnectedFaces() |
int |
removeDisconnectedVertices() |
boolean |
removeFace(Face face)
Removes a face from this mesh.
|
boolean |
removeFaceFast(Face face)
Removes a face from this mesh, potentially changing order of faces
|
java.util.ArrayList<java.lang.Integer> |
removeFaces(java.util.Collection<Face> faces)
Removes a set of faces from this mesh, as indicated by a collection.
|
java.util.ArrayList<java.lang.Integer> |
removeFacesX(java.util.Collection<Face> faces)
Removes a set of faces from this mesh, as indicated by a collection.
|
boolean |
removeOppositeFaces(double cosLimit)
Remove adjacent faces whose normals satisfy n1.dot(n2)
< cosLimit |
void |
render(Renderer renderer,
RenderProps props,
int flags) |
void |
replaceVertices(java.util.List<? extends Vertex3d> vtxs) |
void |
set(double[][] pnts,
int[][] faceIndices)
Sets the vertex points and faces associated with this mesh.
|
void |
set(Point3d[] pnts,
int[][] faceIndices)
Sets the vertex points and faces associated with this mesh.
|
boolean |
setHardEdge(int vidx0,
int vidx1,
boolean hard)
Sets the edge between the vertices indexed by
vidx0 and
vidx1 to be hard, as described for hasHardEdge(v0,v1) . |
boolean |
setHardEdge(Vertex3d v0,
Vertex3d v1,
boolean hard)
|
void |
setHardEdgesFromFaceNormals(double cosThreshold)
Sets edges to be "hard" based on angle between faces.
|
boolean |
setHardEdgesFromNormals() |
void |
setMeshToWorld(RigidTransform3d X)
Sets the spatial transform this mesh.
|
void |
setMultipleAutoNormals(boolean enable)
Enable or disable multiple vertex normals when normals are computed
automatically, as described for
getMultipleAutoNormals() . |
void |
setSubdivisions(int subdivisions)
Setting this generates a new mesh therefore any previous meshes are
invalidated and should be discarded.
|
boolean |
supportsMassDistribution(MassDistribution dist)
Queries whether or not a given mass distrubution is supported for this
mesh type.
|
void |
transform(AffineTransform3dBase X)
Applies an affine transformation to the vertices of this mesh.
|
void |
transform(VectorTransformer3d T)
Applies a vector transformation to the vertices of this mesh.
|
RigidTransform3d |
translateToCenterOfVolume()
Translates the vertices of this mesh so that its origin coincides
with the center of volume.
|
void |
triangulate()
Modifies this mesh to ensure that all faces are triangles.
|
void |
updateFaceNormals()
Updates face normals if necessary.
|
void |
updateRenderNormals()
Updates face rendering normals if necessary.
|
void |
updateSubdivisionMesh(PolygonalMesh mesh)
Updates a subdivision mesh.
|
void |
write(java.io.PrintWriter pw,
NumberFormat fmt,
boolean zeroIndexed)
Writes this mesh to a PrintWriter, using an Alias Wavefront "obj" file
format.
|
void |
write(java.io.PrintWriter pw,
NumberFormat fmt,
boolean zeroIndexed,
boolean facesClockwise)
Writes this mesh to a PrintWriter, using an Alias Wavefront "obj" file
format.
|
void |
writePoly(java.io.PrintStream ps) |
void |
writePoly(java.lang.String nodeString) |
void |
writeWorld(java.io.PrintStream ps) |
addVertex, addVertex, addVertex, addVertex, checksum, clearColors, clearNormals, clearRenderProps, clearTextureCoords, computeAverageRadius, computeCentroid, computeLocalBounds, computeOBB, computeOBB, computeRadius, computeWorldBounds, containsVertex, createFeatureIndices, createRenderProps, getColor, getColorIndices, getColorInterpolation, getColors, getFeatureColor, getFeatureColoringEnabled, getFeatureIndexOffsets, getFeatureNormal, getFeatureTextureCoords, getLocalBounds, getMeshToWorld, getMeshToWorld, getName, getNormal, getNormalIndices, getNormals, getRadius, getRenderNormal, getRenderProps, getSelection, getTextureCoords, getTextureCoords, getTextureIndices, getVersion, getVertex, getVertexColoringEnabled, getVertexColorMixing, getVertices, getWorldBounds, getXMeshToWorldRender, hasColors, hasExplicitColors, hasExplicitNormals, hasNormals, hasTextureCoords, isColorsFixed, isEmpty, isFeatureColored, isFixed, isRenderBuffered, isSelectable, isTextureCoordsFixed, isVertexColored, meshToWorldIsIdentity, numColors, numNormals, numSelectionQueriesNeeded, numTextureCoords, numVertices, perturb, prerender, read, read, read, removeVertex, removeVertexFast, removeVertices, render, saveRenderInfo, scale, scale, setColor, setColor, setColor, setColor, setColorInterpolation, setColors, setColorsFixed, setFeatureColoringEnabled, setFixed, setName, setNormal, setNormals, setRenderBuffered, setRenderProps, setTextureCoords, setTextureCoords, setTextureCoordsFixed, setVertexColoringEnabled, setVertexColorMixing, size, transformToLocal, transformToLocal, transformToOBB, transformToOBB, transformToWorld, transformToWorld, translate, translateToCentroid, updateBounds, write, write, write, write
public static final int NON_MANIFOLD_EDGES
public static final int NON_MANIFOLD_VERTICES
public static final int OPEN_EDGES
public static final int ISOLATED_VERTICES
public static final int ALL_DEGENERACIES
public boolean canSelfIntersect
public static int computedFaceNormals
public PolygonalMesh()
public PolygonalMesh(java.lang.String fileName) throws java.io.IOException
fileName
- name of the file containing the mesh descriptionjava.io.IOException
- if an I/O error occurred or if the file
type is not compatible with polygonal meshespublic PolygonalMesh(java.io.File file) throws java.io.IOException
file
- file containing the mesh descriptionjava.io.IOException
- if an I/O error occurred or if the file
type is not compatible with polygonal meshespublic PolygonalMesh(PolygonalMesh old)
public void notifyVertexPositionsModified()
notifyVertexPositionsModified
in class MeshBase
public void updateFaceNormals()
public void updateRenderNormals()
public boolean faceNormalsValid()
public RenderProps createRenderProps(HasProperties host)
createRenderProps
in class MeshBase
host
- if non-null, is used to initialize inherited valuespublic boolean isTriangular()
public boolean isQuad()
public boolean hasIsolatedVertices()
true
if this mesh has isolated vertices.public boolean hasOpenEdges()
true
if this mesh has open edges.public boolean hasNonManifoldEdges()
hasOpenEdges()
will return true
.true
if this mesh has non-manifold edges.hasOpenEdges()
public boolean hasNonManifoldVertices()
hasOpenEdges()
will return
true
.
If hasNonManifoldEdges()
returns true
, then this
predicate will return true
also.
true
if this mesh has non-manifold vertices.hasOpenEdges()
,
hasNonManifoldEdges()
public boolean isClosed()
isManifold()
returns true
), and also has no open edges, so that hasOpenEdges()
returns false
.public boolean isManifold()
hasNonManifoldEdges()
, hasNonManifoldVertices()
, and hasIsolatedVertices()
all returning false
.
Note: some definitions of "manifold" also require that the mesh does not self-intersect. This primitive does not check for this.
public boolean isWatertight()
hasOpenEdges()
, hasNonManifoldEdges()
, and hasIsolatedVertices()
all returning false
.public java.util.ArrayList<Vertex3d> findNonManifoldVertices()
public java.util.ArrayList<Face> getFaces()
Face
.
Modifying these elements will modify the mesh.public int numFaces()
public Face getFace(int idx)
idx
- index of the facepublic HalfEdge getHalfEdge(int idx)
3 * faceIdx + edgeNumwhere
faceIdx
is the index for the edge's face, and edgeNum
is the edge's number with respect to the face (with face.firstHalfEdge()
corresponding to 0).idx
- index of the half-edgepublic int countEdges()
public DistanceGrid getSignedDistanceGrid()
public DistanceGrid getSignedDistanceGrid(double margin, Vector3i cellDivisions)
public void setMeshToWorld(RigidTransform3d X)
MeshBase
meshToWorldIsIdentity
will subsequently
return true.setMeshToWorld
in class MeshBase
X
- transform from mesh to world coordinatespublic void read(java.io.Reader reader) throws java.io.IOException
write(PrintWriter,NumberFormat,boolean)
.public void read(java.lang.String input)
write(PrintWriter,NumberFormat,boolean)
.input
- supplied input description of the meshpublic void read(java.lang.String input, boolean zeroIndexed)
write(PrintWriter,NumberFormat,boolean)
.input
- supplied input description of the meshpublic void read(ReaderTokenizer rtok, boolean zeroIndexed) throws java.io.IOException
write(PrintWriter,NumberFormat,boolean)
.public void set(Point3d[] pnts, int[][] faceIndices)
pnts
- points from which the vertices are formedfaceIndices
- integer arrays giving the indices of each face. Each index should
correspond to a particular point in pnts.java.lang.IllegalArgumentException
- if a vertex index is out of boundspublic Face addFace(int[] indices)
indices
- integer array giving the vertex indices of the face. Each index should
correspond to a vertex presently associated with this mesh.java.lang.IllegalArgumentException
- if a vertex index is out of boundspublic Face addFace(Vertex3d[] vertices)
vertices
- vertices comprising this faces. Each vertex should be presently contained
in this mesh.java.lang.IllegalArgumentException
- if any vertices are not contained within this meshpublic Face addFace(Vertex3d v0, Vertex3d v1, Vertex3d v2)
v0
- first vertexv1
- second vertexv2
- third vertexjava.lang.IllegalArgumentException
- if any vertices are not contained within this meshpublic Face addFace(int idx0, int idx1, int idx2)
idx0
- first vertex indexidx1
- second vertex indexidx2
- third vertex indexjava.lang.IllegalArgumentException
- if any vertices are not contained within
this meshpublic Face addFace(Vertex3d v0, Vertex3d v1, Vertex3d v2, Vertex3d v3)
v0
- first vertexv1
- second vertexv2
- third vertexv3
- fourth vertexjava.lang.IllegalArgumentException
- if any vertices are not contained within this meshpublic Face addFace(int idx0, int idx1, int idx2, int idx3)
idx0
- first vertex indexidx1
- second vertex indexidx2
- third vertex indexidx3
- fourth vertex indexjava.lang.IllegalArgumentException
- if any vertices are not contained within
this meshpublic boolean removeFace(Face face)
face
- face to removepublic boolean removeFaceFast(Face face)
public java.util.ArrayList<java.lang.Integer> removeFaces(java.util.Collection<Face> faces)
faces
- Collection of faces to removepublic java.util.ArrayList<java.lang.Integer> removeFacesX(java.util.Collection<Face> faces)
faces
- Collection of faces to removepublic void clearFaces()
public int doMergeCloseVertices(double dsqr)
public int mergeCloseVertices(double dist)
dist
. Thus vertices which
are isolated, or not otherwise connected by edges, will be unaffected.
The implementation of this algorithm is not perfect. If the mesh is not closed, and merging results in the alignment of one or more boundary edges, these edges will not be connected. Moreover, the mesh topology may sometimes may it impossible to merge an adjacent vertex without corrupting the mesh topology; in these cases, merges will not be done and a warning will be printed.
dist
- distance within which vertices should be merged.public boolean mergeCoplanarFaces(double cosLimit)
>
cosLimitcosLimit
- limit above which faces should be mergedpublic boolean removeOppositeFaces(double cosLimit)
<
cosLimitcosLimit
- limit above which faces should be removedpublic int numDisconnectedVertices()
public int removeDisconnectedVertices()
public int removeDisconnectedFaces()
public PolygonalMesh[] partitionIntoConnectedMeshes()
null
is returned. At present, the copied meshes do not
preserve face normal or texture information.
The returned meshes are sorted, high to low, by the number of vertices.
public void checkConsistency()
public void set(double[][] pnts, int[][] faceIndices)
pnts
- set of values (x,y,z) from which the vertices are formedfaceIndices
- integer arrays giving the indices of each face. Each index should
correspond to a particular point in pnts.java.lang.IllegalArgumentException
- if a vertex index is out of boundspublic void write(java.io.PrintWriter pw, NumberFormat fmt, boolean zeroIndexed) throws java.io.IOException
write(java.io.PrintWriter,maspack.util.NumberFormat,boolean,boolean)
with facesClockwise
set to false.write
in class MeshBase
pw
- PrintWriter to write this mesh tofmt
- format for writing the vertex coordinates. If null
,
a format of "%.8g"
is assumed.zeroIndexed
- if true, index numbering for mesh vertices starts at 0. Otherwise,
numbering starts at 1.java.io.IOException
public void write(java.io.PrintWriter pw, NumberFormat fmt, boolean zeroIndexed, boolean facesClockwise) throws java.io.IOException
v 0.0 0.0 0.0 v 1.0 0.0 0.0 v 0.0 1.0 0.0 v 0.0 0.0 1.0 f 1 2 3 f 0 2 1 f 0 3 2 f 0 1 3
The format used to print vertex coordinates is specified by a
NumberFormat
.
pw
- PrintWriter to write this mesh tofmt
- format for writing the vertex coordinates. If null
,
a format of "%.8g"
is assumed.zeroIndexed
- if true, index numbering for mesh vertices starts at 0. Otherwise,
numbering starts at 1.facesClockwise
- if true, face indices are written clockwise instead of the
usual counter-clockwise convention.java.io.IOException
public void writePoly(java.lang.String nodeString) throws java.lang.Exception
java.lang.Exception
public void writePoly(java.io.PrintStream ps) throws java.lang.Exception
java.lang.Exception
public RigidTransform3d translateToCenterOfVolume()
public void transform(AffineTransform3dBase X)
public void inverseTransform(AffineTransform3dBase X)
inverseTransform
in class MeshBase
X
- affine transformationpublic void transform(VectorTransformer3d T)
public void inverseTransform(VectorTransformer3d T)
inverseTransform
in class MeshBase
T
- vector transformationpublic int getRenderHints()
TRANSPARENT
and
TWO_DIMENSIONAL
.getRenderHints
in interface IsRenderable
getRenderHints
in class MeshBase
public void prerender(RenderProps props)
public void render(Renderer renderer, RenderProps props, int flags)
public PolygonalMesh getSubdivisionMesh()
public void updateSubdivisionMesh(PolygonalMesh mesh)
mesh
- Must be a mesh generated by calling getSubdivisionMesh on this mesh.public void interpolate(Point3d p, Face f, double u, double v)
f
- The face to interpolate.u
- The weighting of the first vertice.v
- The weighting of the second vertice.public int getSubdivisions()
public void setSubdivisions(int subdivisions)
subdivisions
- The number of times to subdivide each triangle.public void extendOpenEdges(double amount)
amount
- The amount to extend it by.public void triangulate()
public int numHardEdges()
public void clearHardEdges()
public boolean setHardEdge(int vidx0, int vidx1, boolean hard)
vidx0
and
vidx1
to be hard, as described for hasHardEdge(v0,v1)
. If so such edge
exists, the method returns false
.vidx0
- first vertex indexvidx1
- second vertex indextrue
if the edge existspublic boolean setHardEdge(Vertex3d v0, Vertex3d v1, boolean hard)
v0
and v1
to
be hard, as described for hasHardEdge(v0,v1)
. If no such edge exists, or if the edge
corresponds only to a single half-edge, the method returns
false
.v0
- first vertexv1
- second vertextrue
if the edge existspublic boolean hasHardEdge(int vidx0, int vidx1)
true
if the edge between the vertices indexed by
vidx0
and vidx1
exists and is hard, as
described for hasHardEdge(v0,v1)
.vidx0
- first vertex indexvidx1
- second vertex indextrue
if the edge exists and is hard.public boolean hasHardEdge(Vertex3d v0, Vertex3d v1)
true
if the edge between vertices v0
and v1
exists and is hard. A hard setting is used as a hint
that the edge is associated with an actual discontinuity in the surface
derivative, and that it may be desirable to render it crisply even when
using smooth shading.v0
- first vertexv1
- second vertextrue
if the edge exists and is hard.public double checkFaceNormals()
public int numDegenerateFaces()
public void checkForDegenerateFaces()
public PolygonalMesh copy()
public PolygonalMesh clone()
MeshBase
public void replaceVertices(java.util.List<? extends Vertex3d> vtxs)
replaceVertices
in class MeshBase
public void addMesh(MeshBase mesh)
public void addMesh(PolygonalMesh mesh, boolean respectTransforms)
mesh
- Mesh to be added to this meshpublic double computeVolume()
public double computeArea()
public double computeAverageEdgeLength()
public java.util.ArrayList<Face> findBorderFaces()
public java.util.ArrayList<HalfEdge> findBorderEdges()
public java.util.ArrayList<Vertex3d> findNeighbouringVertices(Vertex3d vtx, double dist)
vtx
that are within a
distance dist
of vtx
. The returned list includes vtx
as its first component.
The method will not necessarily return all vertices that are
within dist
of vtx
. For example, if the mesh folds back
on itself, then vertices in the ``fold back'' region may be missed.
vtx
- vertex for which nearest vertices are desireddist
- search distance from vtx
public double computeVolumeIntegrals(Vector3d mov1, Vector3d mov2, Vector3d pov)
mov1
- if non-null, returns the first moment of volumemov2
- if non-null, returns the second moment of volumepov
- if non-null, returns the product of volumepublic RigidTransform3d computePrincipalAxes()
public static RigidTransform3d computePrincipalAxes(PolygonalMesh mesh)
public BVTree getBVTree()
MeshBase
public void clearBVTree()
public double distanceToPoint(Point3d pnt)
getBVTree()
.pnt
- point for which distance should be computed (world coords)java.lang.IllegalArgumentException
- if this mesh is not triangularpublic double distanceToPoint(Point3d nearPnt, Point3d pnt)
getBVTree()
.nearPnt
- if not null
, returns the nearest
point on the mesh in world coordinates.pnt
- point for which distance should be computed (world coords)java.lang.IllegalArgumentException
- if this mesh is not triangularpublic Face nearestFaceToPoint(Point3d nearPnt, Vector2d uv, Point3d pnt)
getBVTree()
.nearPnt
- if not null
, returns the nearest
point on the face in world coordinates.uv
- if not null
, returns the UV coordinates of the
nearest point on the face. These are the barycentric coordinates with
respect to the second and third vertices.pnt
- point for which the nearest face should be found.null
if the mesh contains no faces.java.lang.IllegalArgumentException
- if this mesh is not triangularpublic int pointIsInside(Point3d pnt)
getBVTree()
.
The method works by counting the number of times a random ray cast from
the point intersects the mesh. Degeneracies are detected and result in
another ray being cast. Whether or not the point is on the mesh is
determined using a numerical tolerance computed from the mesh's overall
dimensions. In rare cases, the method may be unable to determine whether
the point is inside or outside, in which case the method returns -1. In
such cases, or if one wishes to distinquish whether the point is outside
vs. ``on'' the mesh, it may be useful to call the underlying BVFeatureQuery
method isInsideMesh()
directly, which offers more control.pnt
- point to check.pnt
is inside, 0 if outside, or -1 if the
method is can't find an answer.java.lang.IllegalArgumentException
- if this mesh is not triangularpublic void writeWorld(java.io.PrintStream ps) throws java.io.IOException
java.io.IOException
public boolean epsilonEquals(MeshBase base, double eps)
eps
).epsilonEquals
in class MeshBase
public double computeInertia(SpatialInertia M, double density)
M
- returns the computed spatial inertiadensity
- density of the volumepublic double computeCentreOfVolume(Vector3d c)
public SpatialInertia createInertia(double density)
density
- density of the volumepublic SpatialInertia createInertia(double mass, MassDistribution dist)
createInertia
in class MeshBase
mass
- overall massdist
- how the mass is distributed across the featurespublic boolean supportsMassDistribution(MassDistribution dist)
supportsMassDistribution
in class MeshBase
true
if the indicated mass distrubution is supportedpublic boolean isBorderVertex(Vertex3d vtx)
public int countConnected()
public int countBorders()
public double countGenus()
public void flip()
public int[] createVertexIndices()
MeshBase
The indices are zero-based and specify the vertex indices for
each mesh feature. The number of indices and their structure hence
depends on the mesh subclass: for PolygonalMesh
meshes,
this gives the vertices for each face; for PolylineMesh
, the
vertices for each polyline, and for PointMesh
, the vertices
for each point. For example, assume that we have a
PolygonalMesh
with four vertices and
four triangles arranged to form a tetrahedron, so that the vertex
indices for each triangular face are given by (0, 2, 1)
,
(0, 3, 2)
, (0, 1, 3)
,
and (1, 2, 3)
. Then the returned vertex
indices will be
0 2 1 0 3 2 0 1 3 1 2 3
createVertexIndices
in class MeshBase
public int numFeatures()
MeshBase
numFeatures
in class MeshBase
public boolean hasAutoNormalCreation()
true
if this mesh automatically creates a default
set of normals if MeshBase.getNormals()
is called and no normals have been
explicitly set using MeshBase.setNormals(java.util.List<maspack.matrix.Vector3d>, int[])
.hasAutoNormalCreation
in class MeshBase
true
if this mesh automatically creates normals.public boolean getWriteNormals()
true
if this mesh's normals should be written
to a file. This will be the case if the normals were explicitly
set, or if they were automatically created using information
(such as hard edges) that cannot be easily reconstructed from the
information written to standard file formats.getWriteNormals
in class MeshBase
true
if the normals should be written to a filepublic void setMultipleAutoNormals(boolean enable)
getMultipleAutoNormals()
.enable
- enables or disables automatic computation of
multiple vertex normals.public boolean getMultipleAutoNormals()
true
if multiple vertex normals are allowed when
normals are computed automatically. If allowed, then a different normal
will be computed for each contiguous region of faces about the vertex
that is delimited by an open or hard edge (see hasHardEdge(Vertex3d,Vertex3d)
). Note that vertices will be associated
with multiple normals only when the surrounding faces contain open
or hard edges.true
if multiple vertex normals are allowedpublic void autoGenerateNormals()
public void setHardEdgesFromFaceNormals(double cosThreshold)
cosThreshold
- dot product between face normals is below this threshold, marks edge as hardpublic int[] computeVertexNormals(java.util.ArrayList<Vector3d> normals, boolean multiNormals)
multiNormals
is true
, then
multiple normals may be computed for each vertex, with different normals
being computed for edge regions that are separated by open or hard
edges. Otherwise, only one normal is computed per vertex.
If normals
is passed in with zero size, then the normals
are computed and returned in new Vector3d
objects that are
and added to it. Also, the method returns a set of computed normal
indices. This option is used for the initial creation of normals.
If normals
is passed in with non-zero size, then it is
assumed to contain enough Vector3d
objects to store all the
computed normals, and the method returns null
. This option
is used for updating normals.
normals
- returns the computed normalsmultiNormals
- if true
, then multiple normals
may be computed for each vertexnormals
has zero size,
otherwise null
.public boolean setHardEdgesFromNormals()
public void printDegenerateFaces()
public void printDegeneracies(int printCode)
printCode
:
public void printDegeneracies()
public int estimateMemoryUsage()
numBytes = 84*F + 92*V + 64*Hwhere F, V and H are the numbers of faces, vertices, and half edges, respectively. This number is only a rough estimate and assumes that references require 4 bytes and not 8.