PartitionedMesh
-
android
class PartitionedMesh
An immutable** complex shape expressed as a set of triangles. This is used to represent the shape of a stroke or other complex objects. The mesh may be divided into multiple partitions, which enables certain brush effects (e.g. "multi-coat"), and allows ink to create strokes using greater than 2^16 triangles (which must be rendered in multiple passes).
A PartitionedMesh may optionally have one or more "outlines", which are polylines that traverse some or all of the vertices in the mesh; these are used for path-based rendering of strokes. This supports disjoint meshes such as dashed lines.
PartitionedMesh provides fast intersection and coverage testing by use of an internal spatial index.
** PartitionedMesh is technically not immutable, as the spatial index is lazily instantiated; however, from the perspective of a caller, its properties do not change over the course of its lifetime. The entire object is thread-safe.
Summary
Public functions |
||
|---|---|---|
Box? |
Returns the minimum bounding box of the |
android
|
@FloatRange(from = 0.0, to = 1.0) Float |
computeCoverage(box: Box, boxToThis: AffineTransform)Computes an approximate measure of what portion of this |
android
|
@FloatRange(from = 0.0, to = 1.0) Float |
computeCoverage(Computes an approximate measure of what portion of this |
android
|
@FloatRange(from = 0.0, to = 1.0) Float |
computeCoverage(Computes an approximate measure of what portion of this |
android
|
@FloatRange(from = 0.0, to = 1.0) Float |
computeCoverage(triangle: Triangle, triangleToThis: AffineTransform)Computes an approximate measure of what portion of this |
android
|
Boolean |
computeCoverageIsGreaterThan(Returns true if the approximate portion of the |
android
|
Boolean |
computeCoverageIsGreaterThan(Returns true if the approximate portion of this |
android
|
Boolean |
computeCoverageIsGreaterThan(Returns true if the approximate portion of the |
android
|
Boolean |
computeCoverageIsGreaterThan(Returns true if the approximate portion of the |
android
|
@IntRange(from = 0) Int |
getOutlineCount(groupIndex: @IntRange(from = 0) Int)Returns the number of outlines of the mesh for the render group at |
android
|
@IntRange(from = 0) Int |
getOutlineVertexCount(Returns the number of vertices that are in the outline at |
android
|
@IntRange(from = 0) Int |
Returns the number of render groups in this mesh. |
android
|
Unit |
Initializes this MutableEnvelope's spatial index for geometry queries. |
android
|
MutableVec |
populateOutlinePosition(Populates |
android
|
open String |
toString() |
android
|
Extension functions |
||
|---|---|---|
Path |
PartitionedMesh.outlinesToPath(renderGroupIndex: @IntRange(from = 0) Int)Returns a |
android
|
Path |
PartitionedMesh.populateOutlines(Replaces the contents of |
android
|
Public functions
computeBoundingBox
fun computeBoundingBox(): Box?
Returns the minimum bounding box of the PartitionedMesh. This will be null if the PartitionedMesh is empty.
computeCoverage
fun computeCoverage(
box: Box,
boxToThis: AffineTransform = AffineTransform.IDENTITY
): @FloatRange(from = 0.0, to = 1.0) Float
Computes an approximate measure of what portion of this PartitionedMesh is covered by or overlaps with box. This is calculated by finding the sum of areas of the triangles that intersect the given box, and dividing that by the sum of the areas of all triangles in the PartitionedMesh, all in the PartitionedMesh's coordinate space. Triangles in the PartitionedMesh that overlap each other (e.g. in the case of a stroke that loops back over itself) are counted individually. Note that, if any triangles have negative area (due to winding, see Triangle.computeSignedArea), the absolute value of their area will be used instead.
On an empty PartitionedMesh, this will always return 0.
Optional argument boxToThis contains the transform that maps from box's coordinate space to this PartitionedMesh's coordinate space, which defaults to AffineTransform.IDENTITY.
computeCoverage
fun computeCoverage(
other: PartitionedMesh,
otherShapeToThis: AffineTransform = AffineTransform.IDENTITY
): @FloatRange(from = 0.0, to = 1.0) Float
Computes an approximate measure of what portion of this PartitionedMesh is covered by or overlaps with the other. This is calculated by finding the sum of areas of the triangles that intersect other, and dividing that by the sum of the areas of all triangles in the PartitionedMesh, all in the PartitionedMesh's coordinate space. Triangles in the PartitionedMesh that overlap each other (e.g. in the case of a stroke that loops back over itself) are counted individually. Note that, if any triangles have negative area (due to winding, see Triangle.computeSignedArea), the absolute value of their area will be used instead.
On an empty PartitionedMesh, this will always return 0.
Optional argument otherShapeToThis contains the transform that maps from other's coordinate space to this PartitionedMesh's coordinate space, which defaults to AffineTransform.IDENTITY.
computeCoverage
fun computeCoverage(
parallelogram: Parallelogram,
parallelogramToThis: AffineTransform = AffineTransform.IDENTITY
): @FloatRange(from = 0.0, to = 1.0) Float
Computes an approximate measure of what portion of this PartitionedMesh is covered by or overlaps with parallelogram. This is calculated by finding the sum of areas of the triangles that intersect the given parallelogram, and dividing that by the sum of the areas of all triangles in the PartitionedMesh, all in the PartitionedMesh's coordinate space. Triangles in the PartitionedMesh that overlap each other (e.g. in the case of a stroke that loops back over itself) are counted individually. Note that, if any triangles have negative area (due to winding, see Triangle.computeSignedArea), the absolute value of their area will be used instead.
On an empty PartitionedMesh, this will always return 0.
Optional argument parallelogramToThis contains the transform that maps from parallelogram's coordinate space to this PartitionedMesh's coordinate space, which defaults to AffineTransform.IDENTITY.
computeCoverage
fun computeCoverage(
triangle: Triangle,
triangleToThis: AffineTransform = AffineTransform.IDENTITY
): @FloatRange(from = 0.0, to = 1.0) Float
Computes an approximate measure of what portion of this PartitionedMesh is covered by or overlaps with triangle. This is calculated by finding the sum of areas of the triangles that intersect the given triangle, and dividing that by the sum of the areas of all triangles in the PartitionedMesh, all in the PartitionedMesh's coordinate space. Triangles in the PartitionedMesh that overlap each other (e.g. in the case of a stroke that loops back over itself) are counted individually. Note that, if any triangles have negative area (due to winding, see Triangle.computeSignedArea), the absolute value of their area will be used instead.
On an empty PartitionedMesh, this will always return 0.
Optional argument triangleToThis contains the transform that maps from triangle's coordinate space to this PartitionedMesh's coordinate space, which defaults to AffineTransform.IDENTITY.
computeCoverageIsGreaterThan
fun computeCoverageIsGreaterThan(
box: Box,
coverageThreshold: Float,
boxToThis: AffineTransform = AffineTransform.IDENTITY
): Boolean
Returns true if the approximate portion of the PartitionedMesh covered by box is greater than coverageThreshold.
This is equivalent to:
computeCoverage(box, boxToThis) coverageThreshold
but may be faster.
On an empty PartitionedMesh, this will always return 0.
Optional argument boxToThis contains the transform that maps from box's coordinate space to this PartitionedMesh's coordinate space, which defaults to AffineTransform.IDENTITY.
computeCoverageIsGreaterThan
fun computeCoverageIsGreaterThan(
other: PartitionedMesh,
coverageThreshold: Float,
otherShapeToThis: AffineTransform = AffineTransform.IDENTITY
): Boolean
Returns true if the approximate portion of this PartitionedMesh covered by the other is greater than coverageThreshold.
This is equivalent to:
computeCoverage(other, otherShapeToThis) coverageThreshold
but may be faster.
On an empty PartitionedMesh, this will always return 0.
Optional argument otherShapeToThis contains the transform that maps from other's coordinate space to this PartitionedMesh's coordinate space, which defaults to AffineTransform.IDENTITY.
computeCoverageIsGreaterThan
fun computeCoverageIsGreaterThan(
parallelogram: Parallelogram,
coverageThreshold: Float,
parallelogramToThis: AffineTransform = AffineTransform.IDENTITY
): Boolean
Returns true if the approximate portion of the PartitionedMesh covered by parallelogram is greater than coverageThreshold.
This is equivalent to:
computeCoverage(parallelogram, parallelogramToThis) coverageThreshold
but may be faster.
On an empty PartitionedMesh, this will always return 0.
Optional argument parallelogramToThis contains the transform that maps from parallelogram's coordinate space to this PartitionedMesh's coordinate space, which defaults to AffineTransform.IDENTITY.
computeCoverageIsGreaterThan
fun computeCoverageIsGreaterThan(
triangle: Triangle,
coverageThreshold: Float,
triangleToThis: AffineTransform = AffineTransform.IDENTITY
): Boolean
Returns true if the approximate portion of the PartitionedMesh covered by triangle is greater than coverageThreshold.
This is equivalent to:
computeCoverage(triangle, triangleToThis) coverageThreshold
but may be faster.
On an empty PartitionedMesh, this will always return 0.
Optional argument triangleToThis contains the transform that maps from triangle's coordinate space to this PartitionedMesh's coordinate space, which defaults to AffineTransform.IDENTITY.
getOutlineCount
fun getOutlineCount(groupIndex: @IntRange(from = 0) Int): @IntRange(from = 0) Int
Returns the number of outlines of the mesh for the render group at groupIndex.
Groups with discontinuous geometry will always have multiple outlines, but even continuous geometry may be drawn with multiple overlapping outlines when this improves rendering quality or performance.
getOutlineVertexCount
fun getOutlineVertexCount(
groupIndex: @IntRange(from = 0) Int,
outlineIndex: @IntRange(from = 0) Int
): @IntRange(from = 0) Int
Returns the number of vertices that are in the outline at outlineIndex in the render group at groupIndex.
getRenderGroupCount
fun getRenderGroupCount(): @IntRange(from = 0) Int
Returns the number of render groups in this mesh. Each outline in the PartitionedMesh belongs to exactly one render group, which are numbered in z-order: the group with index zero should be rendered on bottom; the group with the highest index should be rendered on top.
initializeSpatialIndex
fun initializeSpatialIndex(): Unit
Initializes this MutableEnvelope's spatial index for geometry queries. If a geometry query is made with this shape and the spatial index is not currently initialized, it will be initialized in real time to satisfy that query.
populateOutlinePosition
fun populateOutlinePosition(
groupIndex: @IntRange(from = 0) Int,
outlineIndex: @IntRange(from = 0) Int,
outlineVertexIndex: @IntRange(from = 0) Int,
outPosition: MutableVec
): MutableVec
Populates outPosition with the position of the outline vertex at outlineVertexIndex in the outline at outlineIndex in the render group at groupIndex, and returns outPosition. groupIndex must be less than getRenderGroupCount, outlineIndex must be less getOutlineVertexCount for groupIndex, and outlineVertexIndex must be less than getOutlineVertexCount for groupIndex and outlineIndex.
Extension functions
outlinesToPath
fun PartitionedMesh.outlinesToPath(renderGroupIndex: @IntRange(from = 0) Int): Path
Returns a Path containing the outlines in the render group at renderGroupIndex.
populateOutlines
fun PartitionedMesh.populateOutlines(
renderGroupIndex: @IntRange(from = 0) Int,
out: Path
): Path
Replaces the contents of out with the outline of the render group at renderGroupIndex.
Returns the modified Path to allow chaining calls.