import Vector from "victor" ; import { LinePosition , Position } from "./types" ; export interface Line { source : Vector ; target : Vector ; v : Vector ; } export function fromLinePosition ( line ) { const source = Vector . fromArray ( [ line . x1 , line . y1 ] ) ; const target = Vector . fromArray ( [ line . x2 , line . y2 ] ) ; return { source , target , v : toLineVector ( source , target ) , } ; } export function fromPositions ( sourcePos , targetPos ) { const source = Vector . fromObject ( sourcePos ) ; const target = Vector . fromObject ( targetPos ) ; return { source , target , v : toLineVector ( source , target ) , } ; } export function fromVectors ( source , target ) { return { source , target , v : toLineVector ( source , target ) , } ; } export function toLineVector ( source , target ) { return target . clone ( ) . subtract ( source ) ; } export function toVectorsFromLinePosition ( line ) { return [ Vector . fromArray ( [ line . x1 , line . y1 ] ) , Vector . fromArray ( [ line . x2 , line . y2 ] ) ] ; } export function getCenterOfLinePosition ( line ) { return Vector . fromArray ( [ ( line . x1 + line . x2 ) / 2 , ( line . y1 + line . y2 ) / 2 ] ) ; } param p param line returns export function getNearestPoint ( p , line ) { const n = line . v . clone ( ) . normalize ( ) ; const lp = line . source ; const a = p . clone ( ) . subtract ( lp ) ; const dot = n . dot ( a ) ; const near = lp . clone ( ) . add ( n . multiplyScalar ( dot ) ) ; return near ; } param p param line returns export function getDistanceToNearestPoint ( p , line ) { const p2 = line . source ; const v2 = line . v ; const v2len = v2 . lengthSq ( ) ; if ( v2len === 0 ) { return 0 ; } const t = v2 . clone ( ) . dot ( p . clone ( ) . subtract ( p2 ) ) / v2len ; const tv2 = v2 . clone ( ) . multiplyScalar ( t ) ; const h = p2 . clone ( ) . add ( tv2 ) ; return h . subtract ( p ) . length ( ) ; } export function getIntersectionOfLineTargetAndCircle ( source , target , center , radius ) { const p = target . clone ( ) ; const length = p . subtract ( center ) . lengthSq ( ) ; const contains = length - ( radius * radius ) <= Math . pow ( 1 , - 10 ) ; if ( ! contains ) return null ; const line = fromVectors ( source , target ) ; const h = getNearestPoint ( center , line ) ; const hp = h . clone ( ) . subtract ( center ) ; const hpLen = hp . length ( ) ; if ( radius < hpLen ) return null ; if ( radius === hpLen ) return h ; const t = Math . sqrt ( radius ** 2 - hpLen ** 2 ) ; const tv = line . v . normalize ( ) . multiplyScalar ( t ) ; return h . subtract ( tv ) ; } export function getIntersectionOfLineTargetAndCircle2 ( source , target , center , radius , nearBy ) { const p = target . clone ( ) ; const length = p . subtract ( center ) . lengthSq ( ) ; const contains = length - ( radius * radius ) <= Math . pow ( 1 , - 10 ) ; if ( ! contains ) return null ; const line = fromVectors ( source , target ) ; const h = getNearestPoint ( center , line ) ; const hp = h . clone ( ) . subtract ( center ) ; const hpLen = hp . length ( ) ; if ( radius < hpLen ) return null ; if ( radius === hpLen ) return h ; const t = Math . sqrt ( radius ** 2 - hpLen ** 2 ) ; const tv = line . v . normalize ( ) . multiplyScalar ( t ) ; const ip1 = h . clone ( ) . add ( tv ) ; const ip2 = h . clone ( ) . subtract ( tv ) ; const d1 = calculateDistance ( nearBy , ip1 ) ; const d2 = calculateDistance ( nearBy , ip2 ) ; if ( Math . abs ( d1 - d2 ) < 2 ) { return ip2 ; } return d1 < d2 ? ip1 : ip2 ; } param line1 param line2 returns export function getIntersectionPointOfLines ( line1 , line2 ) { const p2 = line2 . source ; const v = p2 . clone ( ) . subtract ( line1 . source ) ; const v1 = line1 . v ; const v2 = line2 . v ; const t2 = v . cross ( v1 ) / v1 . cross ( v2 ) ; return p2 . clone ( ) . add ( v2 . clone ( ) . multiplyScalar ( t2 ) ) ; } export function getIntersectionOfCircles ( center1 , radius1 , center2 , radius2 , near ) { const c1 = center1 ; const c2 = center2 ; const vC1C2 = c2 . clone ( ) . subtract ( c1 ) ; const a = vC1C2 . magnitude ( ) ; const sumR = radius1 + radius2 ; if ( sumR < a ) return null ; const subR = Math . abs ( radius1 - radius2 ) ; if ( a < subR ) return null ; if ( a === sumR ) { const n = vC1C2 . clone ( ) . normalize ( ) ; const p = center1 . clone ( ) . add ( n . multiplyScalar ( radius1 ) ) ; return p ; } if ( a === subR ) { const n = vC1C2 . clone ( ) . normalize ( ) ; const isLarge = radius1 > radius2 ; const p = center1 . clone ( ) . add ( n . multiplyScalar ( isLarge ? radius1 : - radius1 ) ) ; return p ; } const b = radius1 ; const c = radius2 ; const cos = ( a ** 2 + b ** 2 - c ** 2 ) / ( 2 * a * b ) ; const rc = b * cos ; const rs = Math . sqrt ( b ** 2 - rc ** 2 ) ; const n1 = vC1C2 . clone ( ) . normalize ( ) ; const n2 = Vector . fromArray ( [ - n1 . y , n1 . x ] ) ; const tn1 = n1 . clone ( ) . multiplyScalar ( rc ) ; const sn2 = n2 . clone ( ) . multiplyScalar ( rs ) ; const result1 = center1 . clone ( ) . add ( tn1 ) . add ( sn2 ) ; const result2 = center1 . clone ( ) . add ( tn1 ) . subtract ( sn2 ) ; const d1 = calculateDistance ( result1 , near ) ; const d2 = calculateDistance ( result2 , near ) ; return d1 < d2 ? result1 : result2 ; } export function calculatePerpendicularLine ( line ) { const n1 = line . v . clone ( ) . normalize ( ) . rotate ( Math . PI / 2 ) ; return fromVectors ( line . target , line . target . clone ( ) . add ( n1 ) ) ; } export function calculateRelativeAngleRadian ( line1 , line2 ) { return Math . atan2 ( line1 . v . y * line2 . v . x - line1 . v . x * line2 . v . y , line1 . v . x * line2 . v . x + line1 . v . y * line2 . v . y ) ; } export function calculateCircleCenterAndRadiusBy3Points ( p1 , p2 , p3 ) { const x1 = p1 . x ; const y1 = p1 . y ; const x2 = p2 . x ; const y2 = p2 . y ; const x3 = p3 . x ; const y3 = p3 . y ; const x12 = x1 - x2 ; const y12 = y1 - y2 ; const x32 = x3 - x2 ; const y32 = y3 - y2 ; const x = ( y32 * ( x12 * ( x1 + x2 ) + y12 * ( y1 + y2 ) ) - y12 * ( x32 * ( x3 + x2 ) + y32 * ( y3 + y2 ) ) ) / ( 2 * x12 * y32 - 2 * y12 * x32 ) ; const y = ( - x32 * ( x12 * ( x1 + x2 ) + y12 * ( y1 + y2 ) ) + x12 * ( x32 * ( x3 + x2 ) + y32 * ( y3 + y2 ) ) ) / ( 2 * x12 * y32 - 2 * y12 * x32 ) ; const radius = Math . sqrt ( Math . pow ( x1 - x , 2 ) + Math . pow ( y1 - y , 2 ) ) ; const center = Vector . fromArray ( [ x , y ] ) ; return [ center , radius ] ; } param pos1 param pos2 returns export function calculateDistance ( pos1 , pos2 ) { const x = pos2 . x - pos1 . x ; const y = pos2 . y - pos1 . y ; return Math . sqrt ( Math . pow ( x , 2 ) + Math . pow ( y , 2 ) ) ; } export { Vector } ;