UNPKG

@davepagurek/flo-mat

Version:

Medial / Scale Axis Transform (MAT/SAT) Library.

250 lines (199 loc) 6.26 kB
/** @internal */ declare let _debug_: Debug; import { drawFs } from 'flo-draw'; import { equal, getObjClosestTo } from 'flo-vector2d'; import { Debug } from '../debug.js'; import { ThreeProngForDebugging } from '../three-prong-for-debugging.js'; /** @internal */ export interface IThreeProngDebugFunctions { drawSpokes : (g: SVGGElement, n: number) => void, traceConvergence : (g: SVGGElement, n: number, indx: number) => void, showBoundary : (g: SVGGElement, n: number, indx: number) => void, logδs : (n: number) => void, logNearest : ( showSpokes? : boolean, showTrace? : boolean, showBoundaries? : boolean ) => (g: SVGGElement, p: number[], showDelay?: number) => void } /** * @internal * Draws 3 lines from the given 3-prong center to its 3 contact points. * @param n - The 3-prong's zero-based index. */ function drawSpokes(g: SVGGElement, n: number): void { const threeProng = _debug_.generated.elems.threeProng[n]; const cc = threeProng.circle.center; const poss = threeProng.poss; for (let i=0; i<poss.length; i++) { const pos = poss[i]; drawFs.line(g, [pos.p, cc], 'thin5 red'); } } /** * @internal * Shows the circle for each boundary iteration. * @param n_ - The 3-prong's zero-based index. If ommitted, all will be shown. * @param idx - The specific boundary iteration index to view. If ommitted, all * will be shown. */ function traceConvergence(g: SVGGElement, n_: number, idx: number): void { let sIndx; let eIndx; if (n_ === undefined) { sIndx = 0; eIndx = _debug_.generated.elems.threeProng.length; } else { sIndx = n_; eIndx = n_ + 1; } for (let n=sIndx; n<eIndx; n++) { const forDebugging = _debug_.generated.elems.threeProng[n]; //const g = forDebugging.generated.g; console.log(forDebugging); const candidateThreeProngs = forDebugging.candidateThreeProngs; //----------------------------- //---- Get start and end index //----------------------------- let startIndx; let endIndx; if (n_ === undefined || idx === -1) { startIndx = forDebugging.bestIndx; endIndx = forDebugging.bestIndx + 1; } else { if (idx === undefined) { startIndx = 0; endIndx = candidateThreeProngs.length; } else { startIndx = idx; endIndx = idx + 1; } } //--------------------------------- //---- Draw candidate three-prongs //--------------------------------- for (let i=startIndx; i<endIndx; i++) { const circle = candidateThreeProngs[i].circle; if (forDebugging.bestIndx === i) { drawFs.dot(g, circle.center, 0.2, 'green'); drawFs.circle(g, circle, 'black thin10 nofill'); } else { drawFs.dot(g, circle.center, 0.2, 'cyan'); drawFs.circle(g, circle, 'cyan thin5 nofill'); } } } } /** * @internal * Shows the actual boundary for each iteration. * @param n The 3-prong's zero-based index. * @param idx The specific boundary iteration index to view. If ommitted will * show all. */ function showBoundary(g: SVGGElement, n: number, idx: number): void { const debugInfo = _debug_.generated.elems.threeProng[n]; //const g = debugInfo.generated.g; const candidateThreeProngs = debugInfo.candidateThreeProngs; const startIndx = idx === undefined ? 0 : idx; const endIndx = idx === undefined ? candidateThreeProngs.length : idx; // Draw relevant δs const cpss = debugInfo.cpss; let j = 0; // For each iteration of δ3s (indexed by j) for (let idx=1; idx<cpss.length-1; idx++) { if (!(j >= startIndx && j <= endIndx)) { j++; continue; } const δ3s = [ cpss[0], cpss[idx], cpss[cpss.length-1] ]; // For each of the 3 δs for (let i=0; i<3; i++) { const δ = δ3s[i]; const δS = δ[0]; // Delta Start const δE = δ[1]; // Delta End const posS = δS.cp.pointOnShape; const posE = δE.cp.pointOnShape; const pS = posS.p; const pE = posE.p; const r = 1 + (i*0.5); if (equal(pS, pE)) { drawFs.crossHair(g, pS, 'red thin10 nofill', r); } else { drawFs.crossHair(g, pS, 'green thin10 nofill', r); drawFs.crossHair(g, pE, 'blue thin10 nofill', r); } } j++; } } /** * @internal * @param n The 3-prong's zero-based index. */ function logδs(n: number): void { const threeProng = _debug_.generated.elems.threeProng[n]; console.log(threeProng.cpss); } /** * @internal * @param p */ function logNearest( showSpokes = true, showTrace = true, showBoundaries = true) { return function(g: SVGGElement, p: number[], showDelay = 1000) { const generated = _debug_.generated; const threeProng = getObjClosestTo<ThreeProngForDebugging>( p, generated.elems.threeProng, threeProng => threeProng.circle ? threeProng.circle.center : [0,0] )!; const circle = threeProng.circle; //const g = threeProng.generated.g; console.log(threeProng); const circle2 = { center: circle.center, radius: circle.radius || 1 }; //const draw = _debug_.fs.draw; drawFs.circle(g, circle2, 'blue thin10 nofill', showDelay); drawFs.crossHair(g, circle.center, 'red thin2 nofill', 2, showDelay); if (showSpokes) { drawFs.line(g, [threeProng.poss[0].p, circle.center], 'blue thin5 nofill', showDelay); drawFs.line(g, [threeProng.poss[1].p, circle.center], 'blue thin5 nofill', showDelay); drawFs.line(g, [threeProng.poss[2].p, circle.center], 'blue thin5 nofill', showDelay); } if (showBoundaries) { const boundaries = threeProng.boundaries; const boundaryS = boundaries[0]; const boundaryE = boundaries[boundaries.length-1]; drawFs.beziers(g, boundaryS, 'red thin20 nofill', showDelay); for (let i=1; i<boundaries.length-1; i++) { const boundary = boundaries[i]; drawFs.beziers(g, boundary, 'green thin20 nofill', showDelay); } drawFs.beziers(g, boundaryE, 'blue thin20 nofill', showDelay); } if (showTrace) { const traces = threeProng.traces; for (const trace of traces) { drawFs.polyline(g, trace, 'red thin5 nofill', showDelay) } } } } /** @internal */ const threeProngDebugFunctions: IThreeProngDebugFunctions = { drawSpokes, traceConvergence, showBoundary, logδs, logNearest } export { threeProngDebugFunctions }