import { isArray } from "@thi.ng/checks/is-array" ; import { isNumber } from "@thi.ng/checks/is-number" ; import type { MultiFn1O } from "@thi.ng/defmulti" ; import { defmulti } from "@thi.ng/defmulti/defmulti" ; import type { IShape } from "@thi.ng/geom-api" ; import { DEFAULT_SAMPLES , SamplingOpts } from "@thi.ng/geom-api/sample" ; import { sample as _arcVertices } from "@thi.ng/geom-arc/sample" ; import { resample } from "@thi.ng/geom-resample/resample" ; import { sampleCubic } from "@thi.ng/geom-splines/cubic-sample" ; import { sampleQuadratic } from "@thi.ng/geom-splines/quadratic-sample" ; import { cossin } from "@thi.ng/math/angle" ; import { TAU } from "@thi.ng/math/api" ; import type { Vec } from "@thi.ng/vectors" ; import { add2 , add3 } from "@thi.ng/vectors/add" ; import { cartesian2 } from "@thi.ng/vectors/cartesian" ; import { madd2 } from "@thi.ng/vectors/madd" ; import { set2 } from "@thi.ng/vectors/set" ; import type { AABB } from "./api/aabb.js" ; import type { Arc } from "./api/arc.js" ; import type { Circle } from "./api/circle.js" ; import type { Cubic } from "./api/cubic.js" ; import type { Ellipse } from "./api/ellipse.js" ; import type { Group } from "./api/group.js" ; import type { Path } from "./api/path.js" ; import type { Points } from "./api/points.js" ; import { Polygon } from "./api/polygon.js" ; import type { Polyline } from "./api/polyline.js" ; import type { Quadratic } from "./api/quadratic.js" ; import type { Rect } from "./api/rect.js" ; import { __dispatch } from "./internal/dispatch.js" ; export const vertices = defmulti < any , number | Partial < SamplingOpts > | undefined , Vec [ ] > ( __dispatch , { line : "polyline" , points3 : "points" , quad : "poly" , tri : "poly" , } , { aabb : ( { pos , size } ) => { const [ px , py , pz ] = pos ; const [ qx , qy , qz ] = add3 ( [ ] , pos , size ) ; return [ [ px , py , pz ] , [ px , py , qz ] , [ qx , py , qz ] , [ qx , py , pz ] , [ px , qy , pz ] , [ px , qy , qz ] , [ qx , qy , qz ] , [ qx , qy , pz ] , ] ; } , arc : ( $ , opts ? ) : Vec [ ] => _arcVertices ( $ . pos , $ . r , $ . axis , $ . start , $ . end , opts ) , circle : ( $ , opts = DEFAULT_SAMPLES ) => { const pos = $ . pos ; const r = $ . r ; let [ num , last ] = circleOpts ( opts , r ) ; const delta = TAU / num ; last && num ++ ; const buf = new Array ( num ) ; for ( let i = 0 ; i < num ; i ++ ) { buf [ i ] = cartesian2 ( null , [ r , i * delta ] , pos ) ; } return buf ; } , cubic : ( $ , opts ? ) => sampleCubic ( $ . points , opts ) , ellipse : ( $ , opts = DEFAULT_SAMPLES ) => { const buf = [ ] ; const pos = $ . pos ; const r = $ . r ; let [ num , last ] = circleOpts ( opts , Math . max ( $ . r [ 0 ] , $ . r [ 1 ] ) ) ; const delta = TAU / num ; last && num ++ ; for ( let i = 0 ; i < num ; i ++ ) { buf [ i ] = madd2 ( [ ] , cossin ( i * delta ) , r , pos ) ; } return buf ; } , group : ( { children } ) => children . reduce ( ( acc , $ ) => acc . concat ( vertices ( $ ) ) , < Vec [ ] > [ ] ) , path : ( $ , opts ? ) => { const _opts = isNumber ( opts ) ? { num : opts } : opts ; let verts = [ ] ; for ( let segs = $ . segments , n = segs . length - 1 , i = 0 ; i <= n ; i ++ ) { const s = segs [ i ] ; if ( s . geo ) { verts = verts . concat ( vertices ( s . geo , { ... _opts , last : i === n && ! $ . closed , } ) ) ; } } return verts ; } , points : ( $ ) => $ . points , poly : ( $ , opts ? ) => resample ( $ . points , opts , true ) , polyline : ( $ , opts ? ) => resample ( $ . points , opts ) , quadratic : ( $ , opts ? ) => sampleQuadratic ( $ . points , opts ) , rect : ( $ , opts ) => { const p = $ . pos ; const q = add2 ( [ ] , p , $ . size ) ; const verts = [ set2 ( [ ] , p ) , [ q [ 0 ] , p [ 1 ] ] , q , [ p [ 0 ] , q [ 1 ] ] ] ; return opts != null ? vertices ( new Polygon ( verts ) , opts ) : verts ; } , } ) ; /**
 * Takes array of vectors or an `IShape`. If the latter, calls  vertices * and return result, else returns original array.
 *
 *  param shape export const ensureVertices = ( shape ) => isArray ( shape ) ? shape : vertices ( shape ) ; const circleOpts = ( opts , r ) : [ number , boolean ] => isNumber ( opts ) ? [ opts , false ] : [ opts . theta ? Math . floor ( TAU / opts . theta ) : opts . dist ? Math . floor ( TAU / ( opts . dist / r ) ) : opts . num || DEFAULT_SAMPLES , opts . last === true , ] ;