import type { Fn3 , FnN7 , FnU4 , FnU5 } from "@thi.ng/api" ; import { closestT } from "@thi.ng/geom-closest-point/line" ; import { sign } from "@thi.ng/math/abs" ; import { EPS } from "@thi.ng/math/api" ; import { clamp01 } from "@thi.ng/math/interval" ; import type { MultiVecOpImpl , ReadonlyVec } from "@thi.ng/vectors" ; import { clockwise2 } from "@thi.ng/vectors/clockwise" ; import { distSq } from "@thi.ng/vectors/distsq" ; import { magSq } from "@thi.ng/vectors/magsq" ; import { mixN } from "@thi.ng/vectors/mixn" ; import { signedArea2 } from "@thi.ng/vectors/signed-area" ; import { vop } from "@thi.ng/vectors/vop" ; export const pointInSegment = ( p , a , b , eps = EPS ) => { const t = closestT ( p , a , b ) ; return t !== undefined ? distSq ( p , mixN ( [ ] , a , b , clamp01 ( t ) ) ) < eps * eps : false ; } ; export const pointInCircle = ( p , pos , r ) => distSq ( pos , p ) <= r * r ; export const pointInSphere = pointInCircle ; export const classifyPointInCircle = ( p , pos , r , eps = EPS ) => sign ( r * r - distSq ( pos , p ) , eps ) ; remarks Assumes a,b,c are in ccw order or else result will be have inverted sign.
 *
 * Based on Jonathan R. Shewchuck:
 * http://www.cs.cmu.edu/afs/cs/project/quake/public/code/predicates.c
 *
 * Also see  pointInCircumCircle param p param a param b param c export const pointIn3Circle = ( [ px , py ] , a , b , c ) => { const apx = a [ 0 ] - px ; const apy = a [ 1 ] - py ; const bpx = b [ 0 ] - px ; const bpy = b [ 1 ] - py ; const cpx = c [ 0 ] - px ; const cpy = c [ 1 ] - py ; const abdet = apx * bpy - bpx * apy ; const bcdet = bpx * cpy - cpx * bpy ; const cadet = cpx * apy - apx * cpy ; const alift = apx * apx + apy * apy ; const blift = bpx * bpx + bpy * bpy ; const clift = cpx * cpx + cpy * cpy ; return alift * bcdet + blift * cadet + clift * abdet ; } ; remarks param p param a param b param c param d export const pointIn4Sphere = ( [ px , py , pz ] , a , b , c , d ) => { const apx = a [ 0 ] - px ; const bpx = b [ 0 ] - px ; const cpx = c [ 0 ] - px ; const dpx = d [ 0 ] - px ; const apy = a [ 1 ] - py ; const bpy = b [ 1 ] - py ; const cpy = c [ 1 ] - py ; const dpy = d [ 1 ] - py ; const apz = a [ 2 ] - pz ; const bpz = b [ 2 ] - pz ; const cpz = c [ 2 ] - pz ; const dpz = d [ 2 ] - pz ; const ab = apx * bpy - bpx * apy ; const bc = bpx * cpy - cpx * bpy ; const cd = cpx * dpy - dpx * cpy ; const da = dpx * apy - apx * dpy ; const ac = apx * cpy - cpx * apy ; const bd = bpx * dpy - dpx * bpy ; const abc = apz * bc - bpz * ac + cpz * ab ; const bcd = bpz * cd - cpz * bd + dpz * bc ; const cda = cpz * da + dpz * ac + apz * cd ; const dab = dpz * ab + apz * bd + bpz * da ; const alift = apx * apx + apy * apy + apz * apz ; const blift = bpx * bpx + bpy * bpy + bpz * bpz ; const clift = cpx * cpx + cpy * cpy + cpz * cpz ; const dlift = dpx * dpx + dpy * dpy + dpz * dpz ; return dlift * abc - clift * dab + ( blift * cda - alift * bcd ) ; } ; export const pointInCircumCircle = ( a , b , c , d ) => magSq ( a ) * signedArea2 ( b , c , d ) - magSq ( b ) * signedArea2 ( a , c , d ) + magSq ( c ) * signedArea2 ( a , b , d ) - magSq ( d ) * signedArea2 ( a , b , c ) > 0 ; export const pointInTriangle2 = ( p , a , b , c ) => { const s = clockwise2 ( a , b , c ) ? 1 : - 1 ; return ( s * signedArea2 ( a , c , p ) >= 0 && s * signedArea2 ( b , a , p ) >= 0 && s * signedArea2 ( c , b , p ) >= 0 ) ; } ; export const classifyPointInTriangle2 = ( p , a , b , c , eps = EPS ) => { const s = clockwise2 ( a , b , c ) ? 1 : - 1 ; return sign ( Math . min ( s * signedArea2 ( a , c , p ) , s * signedArea2 ( b , a , p ) , s * signedArea2 ( c , b , p ) ) , eps ) ; } ; export const pointInPolygon2 = ( p , pts ) => { const n = pts . length - 1 ; const px = p [ 0 ] ; const py = p [ 1 ] ; let a = pts [ n ] ; let b = pts [ 0 ] ; let inside = 0 ; for ( let i = 0 ; i <= n ; a = b , b = pts [ ++ i ] ) { inside = classifyPointPolyPair ( px , py , a [ 0 ] , a [ 1 ] , b [ 0 ] , b [ 1 ] , inside ) ; } return inside ; } ; export const classifyPointPolyPair = ( px , py , ax , ay , bx , by , inside ) => ( ( ay < py && by >= py ) || ( by < py && ay >= py ) ) && ( ax <= px || bx <= px ) ? inside ^ ( ax + ( ( py - ay ) / ( by - ay ) ) * ( bx - ax ) < px ? 1 : 0 ) : inside ; export const pointInBox = vop ( 0 ) ; export const pointInRect = pointInBox . add ( 2 , ( [ x , y ] , pos , size ) => x >= pos [ 0 ] && x <= pos [ 0 ] + size [ 0 ] && y >= pos [ 1 ] && y <= pos [ 1 ] + size [ 1 ] ) ; export const pointInAABB = pointInBox . add ( 3 , ( [ x , y , z ] , pos , size ) => x >= pos [ 0 ] && x <= pos [ 0 ] + size [ 0 ] && y >= pos [ 1 ] && y <= pos [ 1 ] + size [ 1 ] && z >= pos [ 2 ] && z <= pos [ 2 ] + size [ 2 ] ) ; pointInBox . default ( ( p , boxMin , boxSize ) => { for ( let i = p . length ; i -- > 0 ; ) { const x = p [ i ] ; const y = boxMin [ i ] ; if ( x < y || x > y + boxSize [ i ] ) return false ; } return true ; } ) ; export const pointInCenteredBox = vop ( 0 ) ; export const pointInCenteredRect = pointInCenteredBox . add ( 2 , ( [ x , y ] , pos , size ) => x >= pos [ 0 ] - size [ 0 ] && x <= pos [ 0 ] + size [ 0 ] && y >= pos [ 1 ] - size [ 1 ] && y <= pos [ 1 ] + size [ 1 ] ) ; export const pointInCenteredAABB = pointInCenteredBox . add ( 3 , ( [ x , y , z ] , pos , size ) => x >= pos [ 0 ] - size [ 0 ] && x <= pos [ 0 ] + size [ 0 ] && y >= pos [ 1 ] - size [ 1 ] && y <= pos [ 1 ] + size [ 1 ] && z >= pos [ 2 ] - size [ 2 ] && z <= pos [ 2 ] + size [ 2 ] ) ; pointInCenteredBox . default ( ( p , boxCenter , boxExtent ) => { for ( let i = p . length ; i -- > 0 ; ) { const x = p [ i ] ; const y = boxCenter [ i ] ; const z = boxExtent [ i ] ; if ( x < y - z || x > y + z ) return false ; } return true ; } ) ;