diff --git a/v2/app/src/components/graph.jsx b/v2/app/src/components/graph.jsx index b2b1423..57ebbd9 100644 --- a/v2/app/src/components/graph.jsx +++ b/v2/app/src/components/graph.jsx @@ -6,11 +6,8 @@ import { OrbitControls, PerspectiveCamera, Bounds, useBounds, Line } from '@reac import Point, {PointContentType} from './point.jsx'; import { useControls, button } from "leva"; import { sendOsc } from '../utils/osc.js'; +import { rgbToCss, getRgbFromIndex } from '../utils/color.js'; -function getColorFromIndex(index, length){ - const hue = (index / length) * 360; - return `hsl(${hue}, 100%, 50%)`; -} export default function Graph({results}){ @@ -45,26 +42,34 @@ export default function Graph({results}){ } function getColorByGroup(result){ - - if(!keywordColor) return 'white'; + + if(!keywordColor) return [1,1,1]; if(!result || !result.payload ) - return 'white'; + return [1,1,1]; - if(result.type==='keyword'){ - return getColorFromIndex(parseInt(result.id), 20); + return getRgbFromIndex(parseInt(result.id), 20); } - const group = result.payload.group[0]; - if(group.distance{ @@ -72,17 +77,51 @@ export default function Graph({results}){ if(!points || points.length===0) return; + const keywords=results.filter((point, index)=>point?.type==='keyword'); + + let i=0; points.forEach((point, index)=>{ + // if keyword, skip + if(results?.[index]?.type==='keyword') return; + // console.log(`send osc Point ${index}: (${point[0].toFixed(2)}, ${point[1].toFixed(2)}, ${point[2].toFixed(2)})`); + let dist=results?.[index]?.payload.group?.map(el=>el.distance) || []; + if(dist.length<4){ + dist = dist.concat(new Array(4 - dist.length).fill(-1)); + } + + let group = results?.[index]?.payload.group?.[0]; + const keyword = keywords.find(kw=>kw.id===group?.id); + const group_index = keyword ? keywords.indexOf(keyword) : -1; + sendOsc('/point',JSON.stringify({ - index: index, + index: i, x: point[0], y: point[1], z: point[2], - content: results?.[index]?.payload.teaser + content: results?.[index]?.payload.teaser, + dist: dist, + color: getColorByGroup(results?.[index]), + group: group_index })); + i++; }); + keywords.forEach((point, index)=>{ + // console.log(`send osc Keyword Point ${index}: (${point[0].toFixed(2)}, ${point[1].toFixed(2)}, ${point[2].toFixed(2)})`); + sendOsc('/keyword',JSON.stringify({ + index: index, + x: point[0], + y: point[1], + z: point[2], + content: JSON.parse(results?.[index]?.payload.text||'{}').title || 'Keyword', + color: getColorByGroup(results?.[index]), + group: index, + })); + }); + + + }, [points]); useEffect(()=>{ if(!results || results.length===0){ @@ -138,7 +177,7 @@ export default function Graph({results}){ result={results?.[index]} showContent={showContent} showKeyword={showKeywords} contentType={contentType} textToShow={textToShow} - color={getColorByGroup(results?.[index])} + color={rgbToCss(getColorByGroup(results?.[index]))} /> ))} diff --git a/v2/app/src/components/point.jsx b/v2/app/src/components/point.jsx index 9cf4d95..2234b56 100644 --- a/v2/app/src/components/point.jsx +++ b/v2/app/src/components/point.jsx @@ -230,7 +230,7 @@ export default function Point({point, index, totalPoints, result, showContent, s if(!result) return; - console.log("Point result:", result); + console.log("Point result:", result, color); if(result?.type==='keyword'){ const title=JSON.parse(result.payload.text??'{}').title; const payloadKeyword={ diff --git a/v2/app/src/utils/color.js b/v2/app/src/utils/color.js new file mode 100644 index 0000000..9336dab --- /dev/null +++ b/v2/app/src/utils/color.js @@ -0,0 +1,41 @@ +export function rgbToCss(rgbArray){ + const r255 = Math.round(rgbArray[0] * 255); + const g255 = Math.round(rgbArray[1] * 255); + const b255 = Math.round(rgbArray[2] * 255); + return `rgb(${r255}, ${g255}, ${b255})`; +} + +export function getRgbFromIndex(index, length){ + const hue = (index / length) * 360; + const saturation = 1; + const lightness = 0.5; + return hslToRgb(hue, saturation, lightness); +} + +function hslToRgb(h, s, l) { + let r, g, b; + // normalize h to [0,1] if provided in degrees (0..360) + let hh = h; + if (hh > 1) hh = hh / 360; + + if (s === 0) { + r = g = b = l; // achromatic + } else { + const hue2rgb = (p, q, t) => { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1/6) return p + (q - p) * 6 * t; + if (t < 1/2) return q; + if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + }; + + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + + r = hue2rgb(p, q, hh + 1 / 3); + g = hue2rgb(p, q, hh); + b = hue2rgb(p, q, hh - 1 / 3); + } + return [r, g, b]; +} \ No newline at end of file diff --git a/v2/app/src/utils/osc.js b/v2/app/src/utils/osc.js index 7c970d9..e5e4bd6 100644 --- a/v2/app/src/utils/osc.js +++ b/v2/app/src/utils/osc.js @@ -3,6 +3,6 @@ import { invoke } from "@tauri-apps/api/core"; const TD_OSC_PORT=7000; export function sendOsc(key, message){ - // console.log("Sending OSC:", key, message); + console.log("Sending OSC:", key, message); invoke('send_osc_message', {key: `${key}`, message: message, host:'0.0.0.0:0', target:`127.0.0.1:${TD_OSC_PORT}`}) } \ No newline at end of file