| import React, { useMemo } from 'react'; |
| import { ForceGraph3D } from 'react-force-graph'; |
|
|
| const KnowledgeMap = ({ papers }) => { |
| |
| const keywords = ['NASA', 'space', 'research', 'astronomy', 'physics', 'biology', 'earth', 'mars', 'satellite', 'mission']; |
|
|
| |
| const extractKeywords = (abstract) => { |
| return keywords.filter(keyword => abstract.toLowerCase().includes(keyword.toLowerCase())); |
| }; |
|
|
| |
| const nodes = useMemo(() => { |
| return papers.map((paper, index) => ({ |
| id: paper.id, |
| name: paper.title, |
| val: 1, |
| color: `hsl(${index * 36}, 70%, 50%)`, |
| pdfLink: paper.pdfLink, |
| keywords: extractKeywords(paper.abstract) |
| })); |
| }, [papers]); |
|
|
| |
| const links = useMemo(() => { |
| const linksArray = []; |
| for (let i = 0; i < nodes.length; i++) { |
| for (let j = i + 1; j < nodes.length; j++) { |
| const sharedKeywords = nodes[i].keywords.filter(k => nodes[j].keywords.includes(k)); |
| if (sharedKeywords.length > 0) { |
| linksArray.push({ |
| source: nodes[i].id, |
| target: nodes[j].id, |
| value: sharedKeywords.length |
| }); |
| } |
| } |
| } |
| return linksArray; |
| }, [nodes]); |
|
|
| const handleNodeClick = (node) => { |
| if (node.pdfLink) { |
| window.open(node.pdfLink, '_blank'); |
| } |
| }; |
|
|
| return ( |
| <div style={{ width: '100vw', height: '100vh', backgroundColor: 'black' }}> |
| <ForceGraph3D |
| graphData={{ nodes, links }} |
| nodeLabel="name" |
| nodeAutoColorBy="id" |
| onNodeClick={handleNodeClick} |
| enableNodeDrag={true} |
|
|