main
reng 1 month ago
parent 3539a8e14f
commit b624bb29f6
  1. 84
      v2/app/src/components/graph.jsx
  2. 2
      v2/app/src/components/point.jsx

@ -10,6 +10,8 @@ import { rgbToCss, getRgbFromIndex } from '../utils/color.js';
import { getRevolution } from '../utils/group.js'; import { getRevolution } from '../utils/group.js';
const getDistance = (v1, v2) => { const getDistance = (v1, v2) => {
if (!v1 || !v2) return Infinity; if (!v1 || !v2) return Infinity;
return Math.sqrt( return Math.sqrt(
@ -28,7 +30,10 @@ export default function Graph({results}){
// const [showContent, setShowContent]=useState(true); // const [showContent, setShowContent]=useState(true);
// const [showKeyword, setShowKeyword]=useState(false); // 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 }, showContent: { value: true },
contentType: { options: Object.values(PointContentType), value: PointContentType.Teaser }, contentType: { options: Object.values(PointContentType), value: PointContentType.Teaser },
showKeywords: { value: false }, showKeywords: { value: false },
@ -38,6 +43,8 @@ export default function Graph({results}){
keywordColor: { value: true }, keywordColor: { value: true },
distToKeywords: { value: 3, min: 0.1, max: 10, step: 0.01 }, distToKeywords: { value: 3, min: 0.1, max: 10, step: 0.01 },
useAnimation: {value:false}, 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<minGroupMembers){
// find least distant points to this keyword and assign until minGroupMembers is reached
let nearestPoints=Array(minGroupMembers - count).fill(null);
results.forEach(res => {
if (res.type === 'keyword') return; if (res.type === 'keyword') return;
const d = res.payload?.group?.find(g => g.id === parseInt(kwId))?.distance || Infinity;
// Calculate distance in vector space (using the embedding/vector) if(d < distToKeywords && (!nearestPoints.some(p => p && p.id === res.id))) {
const d = getDistance(res.vector, kw.vector); nearestPoints.push({...res ,d});
if (d < minDocDist) {
minDocDist = d;
nearestPoint = res;
} }
}); });
// Re-assign the nearest point to this keyword nearestPoints = nearestPoints.filter(p => p !== null).slice(0, minGroupMembers - count);
if (nearestPoint) {
console.log(`Force assigning point ${nearestPoint.id} to empty group ${kw.id}`); nearestPoints.forEach(p => {
nearestPoint.payload.group = [{ id: kw.id, distance: minDocDist }]; // console.log(`Assigning point ${p.id} to group ${kwId} to meet minGroupMembers.`);
groupCounts[kw.id]++; 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; let i=0;
@ -244,10 +272,10 @@ export default function Graph({results}){
return; return;
} }
generateLinesFromPoints(points, drawDistance).then(newLines=>{ // generateLinesFromPoints(points, drawDistance).then(newLines=>{
console.log("Lines updated due to drawDistance change:", newLines); // console.log("Lines updated due to drawDistance change:", newLines);
setLines(newLines); // setLines(newLines);
}); // });
},[drawDistance]); },[drawDistance]);
@ -266,10 +294,10 @@ export default function Graph({results}){
console.log("3D Points:", newPoints); console.log("3D Points:", newPoints);
setPoints(newPoints); setPoints(newPoints);
generateLinesFromPoints(newPoints, drawDistance).then(newLines=>{ // generateLinesFromPoints(newPoints, drawDistance).then(newLines=>{
console.log("Lines:", newLines); // console.log("Lines:", newLines);
setLines(newLines); // setLines(newLines);
}); // });
}); });

@ -236,7 +236,7 @@ export default function Point({point, index, totalPoints, result, showContent, s
if(!result) return; if(!result) return;
console.log("Point result:", result, color); // console.log("Point result:", result, color);
if(result?.type==='keyword'){ if(result?.type==='keyword'){
const title=JSON.parse(result.payload.text??'{}').title; const title=JSON.parse(result.payload.text??'{}').title;
const payloadKeyword={ const payloadKeyword={

Loading…
Cancel
Save