diff --git a/v2/app/src/components/graph.jsx b/v2/app/src/components/graph.jsx index 2b220a8..2a095e9 100644 --- a/v2/app/src/components/graph.jsx +++ b/v2/app/src/components/graph.jsx @@ -10,6 +10,8 @@ import { rgbToCss, getRgbFromIndex } from '../utils/color.js'; import { getRevolution } from '../utils/group.js'; + + const getDistance = (v1, v2) => { if (!v1 || !v2) return Infinity; return Math.sqrt( @@ -28,7 +30,10 @@ export default function Graph({results}){ // const [showContent, setShowContent]=useState(true); // const [showKeyword, setShowKeyword]=useState(false); - const { showContent, contentType, showKeywords, showLines, textToShow, drawDistance, distToKeywords, keywordColor, useAnimation } = useControls({ + const { showContent, contentType, showKeywords, showLines, textToShow, drawDistance, + distToKeywords, keywordColor, useAnimation, + maxGroupMembers, minGroupMembers, + } = useControls({ showContent: { value: true }, contentType: { options: Object.values(PointContentType), value: PointContentType.Teaser }, showKeywords: { value: false }, @@ -38,6 +43,8 @@ export default function Graph({results}){ keywordColor: { value: true }, distToKeywords: { value: 3, min: 0.1, max: 10, step: 0.01 }, useAnimation: {value:false}, + maxGroupMembers: { value: 30, min: 1, max: 100 }, + minGroupMembers: { value: 10, min: 1, max: 50 }, }); @@ -106,32 +113,53 @@ export default function Graph({results}){ } }); - // --- STEP 2: Force Assignment for Empty Groups --- - keywords.forEach(kw => { - if (groupCounts[kw.id] === 0) { - // Find the nearest data point that isn't a keyword itself - let nearestPoint = null; - let minDocDist = Infinity; - results.forEach((res, idx) => { + console.log("Initial group counts:", groupCounts); + + Object.entries(groupCounts).forEach(([kwId, count]) => { + // console.log(`Group ${kwId} has ${count} points assigned.`); + + if(count>=minGroupMembers && count<=maxGroupMembers){ + return; + } + + if(count { if (res.type === 'keyword') return; - - // Calculate distance in vector space (using the embedding/vector) - const d = getDistance(res.vector, kw.vector); - if (d < minDocDist) { - minDocDist = d; - nearestPoint = res; + const d = res.payload?.group?.find(g => g.id === parseInt(kwId))?.distance || Infinity; + if(d < distToKeywords && (!nearestPoints.some(p => p && p.id === res.id))) { + nearestPoints.push({...res ,d}); } }); - // Re-assign the nearest point to this keyword - if (nearestPoint) { - console.log(`Force assigning point ${nearestPoint.id} to empty group ${kw.id}`); - nearestPoint.payload.group = [{ id: kw.id, distance: minDocDist }]; - groupCounts[kw.id]++; - } + nearestPoints = nearestPoints.filter(p => p !== null).slice(0, minGroupMembers - count); + + nearestPoints.forEach(p => { + // console.log(`Assigning point ${p.id} to group ${kwId} to meet minGroupMembers.`); + p.payload.group = [{ id: kwId, distance: p.d }]; + groupCounts[kwId]++; + }); + } + + if(count>maxGroupMembers){ + // find most distant points to this keyword and unassign until maxGroupMembers is reached + let farthestPoints=results.filter(res => res.type !== 'keyword' && res.payload?.group?.[0]?.id === parseInt(kwId)) + .sort((a,b) => (b.payload.group[0].distance || Infinity) - (a.payload.group[0].distance || Infinity)) + .slice(0, count - maxGroupMembers); + + farthestPoints.forEach(p => { + // console.log(`Unassigning point ${p.id} from group ${kwId} to meet maxGroupMembers.`); + p.payload.group = p.payload.group.filter(g => g.id !== parseInt(kwId)); + groupCounts[kwId]--; + }); } + }); + + console.log("Final group counts after adjustment:", groupCounts); let i=0; @@ -244,10 +272,10 @@ export default function Graph({results}){ return; } - generateLinesFromPoints(points, drawDistance).then(newLines=>{ - console.log("Lines updated due to drawDistance change:", newLines); - setLines(newLines); - }); + // generateLinesFromPoints(points, drawDistance).then(newLines=>{ + // console.log("Lines updated due to drawDistance change:", newLines); + // setLines(newLines); + // }); },[drawDistance]); @@ -266,10 +294,10 @@ export default function Graph({results}){ console.log("3D Points:", newPoints); setPoints(newPoints); - generateLinesFromPoints(newPoints, drawDistance).then(newLines=>{ - console.log("Lines:", newLines); - setLines(newLines); - }); + // generateLinesFromPoints(newPoints, drawDistance).then(newLines=>{ + // console.log("Lines:", newLines); + // setLines(newLines); + // }); }); diff --git a/v2/app/src/components/point.jsx b/v2/app/src/components/point.jsx index ca0708f..301fb86 100644 --- a/v2/app/src/components/point.jsx +++ b/v2/app/src/components/point.jsx @@ -236,7 +236,7 @@ export default function Point({point, index, totalPoints, result, showContent, s if(!result) return; - console.log("Point result:", result, color); + // console.log("Point result:", result, color); if(result?.type==='keyword'){ const title=JSON.parse(result.payload.text??'{}').title; const payloadKeyword={