/** @packageDocumentation * @module Polyface */ import { BagOfCurves, CurveCollection } from "../curve/CurveCollection"; import { LineSegment3d } from "../curve/LineSegment3d"; import { LineString3d } from "../curve/LineString3d"; import { Loop } from "../curve/Loop"; import { Angle } from "../geometry3d/Angle"; import { GrowableXYZArray } from "../geometry3d/GrowableXYZArray"; import { Plane3dByOriginAndUnitNormal } from "../geometry3d/Plane3dByOriginAndUnitNormal"; import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; import { Matrix4d } from "../geometry4d/Matrix4d"; import { MomentData } from "../geometry4d/MomentData"; import { IndexedEdgeMatcher } from "./IndexedEdgeMatcher"; import { IndexedPolyface, Polyface, PolyfaceVisitor } from "./Polyface"; import { RangeLengthData } from "./RangeLengthData"; /** * Structure to return multiple results from volume between facets and plane * @public */ export interface FacetProjectedVolumeSums { /** Summed (signed) volume */ volume: number; /** summed area moments for positive contributions */ positiveProjectedFacetAreaMoments?: MomentData; /** summed area moments for negative contributions */ negativeProjectedFacetAreaMoments?: MomentData; } /** * Enumeration of cases for retaining facets among duplicates * @public */ export declare enum DuplicateFacetClusterSelector { /** retain none of the duplicates */ SelectNone = 0, /** retain any one member among duplicates */ SelectAny = 1, /** retain all members among duplicates */ SelectAll = 2, /** retain one from any cluster with an odd number of faces */ SelectOneByParity = 3 } /** PolyfaceQuery is a static class whose methods implement queries on a polyface or polyface visitor provided as a parameter to each method. * @public */ export declare class PolyfaceQuery { /** copy the points from a visitor into a Linestring3d in a Loop object */ static visitorToLoop(visitor: PolyfaceVisitor): Loop; /** Create a linestring loop for each facet of the polyface. */ static indexedPolyfaceToLoops(polyface: Polyface): BagOfCurves; /** Return the sum of all facets areas. */ static sumFacetAreas(source: Polyface | PolyfaceVisitor | undefined): number; /** sum volumes of tetrahedra from origin to all facets. * * if origin is omitted, the first point encountered (by the visitor) is used as origin. * * If the mesh is closed, this sum is the volume. * * If the mesh is not closed, this sum is the volume of a mesh with various additional facets * from the origin to facets. */ static sumTetrahedralVolumes(source: Polyface | PolyfaceVisitor, origin?: Point3d): number; /** sum (signed) volumes between facets and a plane. * Return a structure with multiple sums: * * volume = the sum of (signed) volumes between facets and the plane. * * positiveAreaMomentData, negativeProjectedFacetAreaMoments = moment data with centroid, area, and second moments with respect to the centroid. * */ static sumVolumeBetweenFacetsAndPlane(source: Polyface | PolyfaceVisitor, plane: Plane3dByOriginAndUnitNormal): FacetProjectedVolumeSums; /** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all all facets, as viewed from origin. */ static sumFacetSecondAreaMomentProducts(source: Polyface | PolyfaceVisitor, origin: Point3d): Matrix4d; /** Return the inertia products [xx,xy,xz,xw, yw, etc] integrated over all tetrahedral volumes from origin */ static sumFacetSecondVolumeMomentProducts(source: Polyface | PolyfaceVisitor, origin: Point3d): Matrix4d; /** Compute area moments for the mesh. In the returned MomentData: * * origin is the centroid. * * localToWorldMap has the origin and principal directions * * radiiOfGyration radii for rotation around the x,y,z axes. */ static computePrincipalAreaMoments(source: Polyface): MomentData | undefined; /** Compute area moments for the mesh. In the returned MomentData: * * origin is the centroid. * * localToWorldMap has the origin and principal directions * * radiiOfGyration radii for rotation around the x,y,z axes. * * The result is only valid if the mesh is closed. * * There is no test for closure. Use `PolyfaceQuery.isPolyfaceClosedByEdgePairing(polyface)` to test for closure. */ static computePrincipalVolumeMoments(source: Polyface): MomentData | undefined; /** * Test if the facets in `source` occur in perfectly mated pairs, as is required for a closed manifold volume. */ static isPolyfaceClosedByEdgePairing(source: Polyface): boolean; /** Test edges pairing in `source` mesh. * * for `allowSimpleBoundaries === false` true return means this is a closed 2-manifold surface * * for `allowSimpleBoundaries === true` true means this is a 2-manifold surface which may have boundary, but is still properly matched internally. * * Any edge with 3 ore more incident facets triggers `false` return. * * Any edge with 2 incident facets in the same direction triggers a `false` return. */ static isPolyfaceManifold(source: Polyface, allowSimpleBoundaries?: boolean): boolean; /** * Test if the facets in `source` occur in perfectly mated pairs, as is required for a closed manifold volume. * If not, extract the boundary edges as lines. * @param source */ static boundaryEdges(source: Polyface | PolyfaceVisitor | undefined, includeDanglers?: boolean, includeMismatch?: boolean, includeNull?: boolean): CurveCollection | undefined; /** Find segments (within the linestring) which project to facets. * * Announce each pair of linestring segment and on-facet segment through a callback. * * Facets are ASSUMED to be convex and planar. */ static announceSweepLinestringToConvexPolyfaceXY(linestringPoints: GrowableXYZArray, polyface: Polyface, announce: AnnounceDrapePanel): any; /** Execute context.projectToPolygon until its work estimates accumulate to workLimit */ private static continueAnnouunceSweepLinestringToConvexPolyfaceXY; private static _asyncWorkLimit; /** Set the limit on work during an async time blocks, and return the old value. * * This should be a large number -- default is 1.0e6 * @internal */ static setAsyncWorkLimit(value: number): number; /** Query the current limit on work during an async time block. * @internal */ static get asyncWorkLimit(): number; /** Number of "await" steps executed in recent async calls. * @internal */ static awaitBlockCount: number; /** Find segments (within the linestring) which project to facets. * * Announce each pair of linestring segment and on-facet segment through a callback. * * Facets are ASSUMED to be convex and planar. * * REMARK: Although this is public, the usual use is via slightly higher level public methods, viz: * * asyncSweepLinestringToFacetsXYReturnChains * @internal */ static asyncAnnounceSweepLinestringToConvexPolyfaceXY(linestringPoints: GrowableXYZArray, polyface: Polyface, announce: AnnounceDrapePanel): Promise; /** Search the facets for facet subsets that are connected with at least vertex contact. * * Return array of arrays of facet indices. */ static partitionFacetIndicesByVertexConnectedComponent(polyface: Polyface | PolyfaceVisitor): number[][]; /** * * Examine the normal orientation for each faces. * * Separate to 3 partitions: * * facets with normal in the positive direction of the vectorToEye (partition 0) * * facets with normal in the negative direction of the vectorToEye (partition 1) * * facets nearly perpendicular to the view vector (partition 2) * * Return array of arrays of facet indices. */ static partitionFacetIndicesByVisibilityVector(polyface: Polyface | PolyfaceVisitor, vectorToEye: Vector3d, sideAngleTolerance: Angle): number[][]; /** * Return the boundary of facets that are facing the eye. * @param polyface * @param visibilitySubset selector among the visible facet sets extracted by partitionFacetIndicesByVisibilityVector * * 0 ==> forward facing * * 1 ==> rear facing * * 2 ==> side facing * @param vectorToEye * @param sideAngleTolerance */ static boundaryOfVisibleSubset(polyface: IndexedPolyface, visibilitySelect: 0 | 1 | 2, vectorToEye: Vector3d, sideAngleTolerance?: Angle): CurveCollection | undefined; /** Clone the facets in each partition to a separate polyface. * */ static clonePartitions(polyface: Polyface | PolyfaceVisitor, partitions: number[][]): Polyface[]; /** If the visitor's client is a polyface, simply return its point array length. * If not a polyface, visit all facets to find the largest index. */ private static visitorClientPointCount; /** Search the facets for facet subsets that are connected with at least edge contact. * * Return array of arrays of facet indices. */ static partitionFacetIndicesByEdgeConnectedComponent(polyface: Polyface | PolyfaceVisitor): number[][]; /** Find segments (within the linestring) which project to facets. * * Assemble each segment pair as a facet in a new polyface * * Facets are ASSUMED to be convex and planar. */ static sweepLinestringToFacetsXYreturnSweptFacets(linestringPoints: GrowableXYZArray, polyface: Polyface): Polyface; /** Find segments (within the linestring) which project to facets. * * Return collected line segments */ static sweepLinestringToFacetsXYReturnLines(linestringPoints: GrowableXYZArray, polyface: Polyface): LineSegment3d[]; /** Find segments (within the linestring) which project to facets. * * Return chains. */ static sweepLinestringToFacetsXYReturnChains(linestringPoints: GrowableXYZArray, polyface: Polyface): LineString3d[]; /** Find segments (within the linestring) which project to facets. * * This is done as a sequence of "await" steps. * * Each "await" step deals with approximately PolyfaceQuery.asyncWorkLimit pairings of (linestring edge) with (facet edge) * * PolyfaceQuery.setAsyncWorkLimit () to change work blocks from default * * Return chains. */ static asyncSweepLinestringToFacetsXYReturnChains(linestringPoints: GrowableXYZArray, polyface: Polyface): Promise; /** * * Examine ranges of facets. * * Return statistical summary of x,y,z ranges. */ static collectRangeLengthData(polyface: Polyface | PolyfaceVisitor): RangeLengthData; /** Clone the facets, inserting vertices (within edges) where points not part of each facet's vertex indices impinge within edges. * */ static cloneWithTVertexFixup(polyface: Polyface): IndexedPolyface; /** * * Each array input structure is: [facetIndex, vertexIndex0, vertexIndex1, ....] * * Vertex indices assumed reversed so it * * vertexIndex0 is the lowest index on the facet * * vertexIndex1 is the lowest neighbor of vertex0 * * first different entry among vertex indices determines lexical result. * * Hence facets with duplicate indices (whether forward or reversed) are considered equal. * @param arrayA * @param arrayB */ private static compareFacetIndexAndVertexIndices; /** * * Return an array of arrays describing facet duplication. * @param includeSingletons if true, non-duplicated facets are included in the output. * * Each array `entry` in the output contains read indices of a cluster of facets with the same vertex indices. */ static collectDuplicateFacetIndices(polyface: Polyface, includeSingletons?: boolean): number[][]; /** * * Return an array of arrays describing facet duplication. * @param includeSingletons if true, non-duplicated facets are included in the output. * * Each array `entry` in the output contains read indices of a cluster of facets with the same vertex indices. */ static announceDuplicateFacetIndices(polyface: Polyface, announceCluster: (clusterFacetIndices: number[]) => void): void; /** Return a new facet set with a subset of facets in source * @param includeSingletons true to copy facets that only appear once * @param clusterSelector indicates whether duplicate clusters are to have 0, 1, or all facets included */ static cloneByFacetDuplication(source: Polyface, includeSingletons: boolean, clusterSelector: DuplicateFacetClusterSelector): Polyface; /** Clone the facets, inserting removing points that are simply within colinear edges. * */ static cloneWithColinearEdgeFixup(polyface: Polyface): Polyface; /** * Set the edge visibility for specified edges in the polyface. * @param polyface mesh to be edited * @param clusters array of edge references * @param value visibility value (true or false) */ private static setEdgeVisibility; /** * Set the visibility of a particular edge of a particular facet. * @param polyface containing polyface * @param facetIndex facet index * @param vertexIndex vertex index (in vertex array) * @param value visibility value. */ static setSingleEdgeVisibility(polyface: IndexedPolyface, facetIndex: number, vertexIndex: number, value: boolean): void; /** Load all half edges from a mesh to an IndexedEdgeMatcher */ static createIndexedEdges(visitor: PolyfaceVisitor): IndexedEdgeMatcher; /** * * Find mated pairs among facet edges. * * Mated pairs have the same vertex indices appearing in opposite order. * * Mark all non-mated pairs invisible. * * At mated pairs * * if angle across the edge is larger than `sharpEdgeAngle`, mark visible * * otherwise mark invisible. * @param mesh mesh to be marked */ static markPairedEdgesInvisible(mesh: IndexedPolyface, sharpEdgeAngle?: Angle): void; /** Try to compute a unit normal for a facet accessible through a visitor. * * Unit normal is computed by `PolygonOps.unitNormal` with the points around the facet. */ static computeFacetUnitNormal(visitor: PolyfaceVisitor, facetIndex: number, result?: Vector3d): Vector3d | undefined; /** * * Mark all edge visibilities in the IndexedPolyface * @param mesh mesh to be marked * @param value true for visible, false for hidden */ static markAllEdgeVisibility(mesh: IndexedPolyface, value: boolean): void; /** * * Examine adjacent facet orientations throughout the mesh * * If possible, reverse a subset to achieve proper pairing. * @param mesh */ static reorientVertexOrderAroundFacetsForConsistentOrientation(mesh: IndexedPolyface): boolean; /** * Set up indexed normals with one normal in the plane of each facet of the mesh. * @param polyface */ static buildPerFaceNormals(polyface: IndexedPolyface): void; /** * * At each vertex of the mesh * * Find clusters of almost parallel normals * * Compute simple average of those normals * * Index to the averages * * For typical meshes, this correctly clusters adjacent normals. * * One cam imagine a vertex with multiple "smooth cone-like" sets of incident facets such that averaging occurs among two nonadjacent cones. But this does not seem to be a problem in practice. * @param polyface polyface to update. * @param toleranceAngle averaging is done between normals up to this angle. */ static buildAverageNormals(polyface: IndexedPolyface, toleranceAngle?: Angle): void; } /** Announce the points on a drape panel. * * The first two points in the array are always along the draped line segment. * * The last two are always on the facet. * * If there are 4 points, those two pairs are distinct, i.e. both segment points are to the same side of the facet. * * If there are 3 points, those two pairs share an on-facet point. * * The panel is ordered so the outward normal is to the right of the draped segment. * @param indexAOnFacet index (in points) of the point that is the first facet point for moving forward along the linestring * @param indexBOnFacet index (in points) of the point that is the second facet point for moving forward along the linestring * @public */ export declare type AnnounceDrapePanel = (linestring: GrowableXYZArray, segmentIndex: number, polyface: Polyface, facetIndex: number, points: Point3d[], indexAOnFacet: number, indexBOnFacet: number) => any; //# sourceMappingURL=PolyfaceQuery.d.ts.map