@@ -43,8 +43,6 @@ interface GraphData {
4343 links : GraphLink [ ]
4444}
4545
46- const START_NODE_ID = 'case_becker'
47-
4846// ────────────────────────────────────────────
4947// Color palette per node type
5048// ────────────────────────────────────────────
@@ -351,17 +349,6 @@ export function RELIEFKnowledgeGraph3D() {
351349
352350 const graphData = useMemo ( ( ) => buildCaseData ( ) , [ ] )
353351
354- const getNodeId = useCallback ( ( ref : string | { id : string } ) => {
355- return typeof ref === 'string' ? ref : ref . id
356- } , [ ] )
357-
358- const isLinkConnectedToSelected = useCallback ( ( link : GraphLink ) => {
359- if ( ! selectedNode ) return false
360- const src = getNodeId ( link . source )
361- const tgt = getNodeId ( link . target )
362- return src === selectedNode . id || tgt === selectedNode . id
363- } , [ getNodeId , selectedNode ] )
364-
365352 useEffect ( ( ) => {
366353 const updateSize = ( ) => {
367354 if ( containerRef . current ) {
@@ -442,8 +429,6 @@ export function RELIEFKnowledgeGraph3D() {
442429
443430 const nodeThreeObject = useCallback ( ( node : GraphNode ) => {
444431 const group = new THREE . Group ( )
445- const isSelected = selectedNode ?. id === node . id
446- const isStartNode = node . id === START_NODE_ID
447432 const color = NODE_COLORS [ node . type ] || '#999'
448433 const size = node . type === 'case' ? 11
449434 : node . type === 'law' ? 10
@@ -464,39 +449,6 @@ export function RELIEFKnowledgeGraph3D() {
464449 const sphere = new THREE . Mesh ( geometry , material )
465450 group . add ( sphere )
466451
467- if ( isStartNode ) {
468- const startGlowGeo = new THREE . SphereGeometry ( size * 1.75 , 28 , 28 )
469- const startGlowMat = new THREE . MeshPhongMaterial ( {
470- color : new THREE . Color ( '#facc15' ) ,
471- transparent : true ,
472- opacity : 0.22 ,
473- shininess : 90 ,
474- } )
475- group . add ( new THREE . Mesh ( startGlowGeo , startGlowMat ) )
476-
477- const startRingGeo = new THREE . TorusGeometry ( size * 1.45 , 0.9 , 16 , 64 )
478- const startRingMat = new THREE . MeshBasicMaterial ( { color : new THREE . Color ( '#fde047' ) } )
479- const startRing = new THREE . Mesh ( startRingGeo , startRingMat )
480- startRing . rotation . x = Math . PI / 2
481- group . add ( startRing )
482- }
483-
484- if ( isSelected ) {
485- const selectedRingGeo = new THREE . TorusGeometry ( size * 1.65 , 0.8 , 16 , 64 )
486- const selectedRingMat = new THREE . MeshBasicMaterial ( { color : new THREE . Color ( '#ffffff' ) } )
487- const selectedRing = new THREE . Mesh ( selectedRingGeo , selectedRingMat )
488- selectedRing . rotation . x = Math . PI / 2
489- group . add ( selectedRing )
490-
491- const selectedHaloGeo = new THREE . SphereGeometry ( size * 1.95 , 24 , 24 )
492- const selectedHaloMat = new THREE . MeshPhongMaterial ( {
493- color : new THREE . Color ( '#ffffff' ) ,
494- transparent : true ,
495- opacity : 0.12 ,
496- } )
497- group . add ( new THREE . Mesh ( selectedHaloGeo , selectedHaloMat ) )
498- }
499-
500452 // Glow effect for case, law, and ai nodes
501453 if ( node . type === 'law' || node . type === 'case' || node . type === 'ai' ) {
502454 const glowGeo = new THREE . SphereGeometry ( size * 1.4 , 24 , 24 )
@@ -510,117 +462,48 @@ export function RELIEFKnowledgeGraph3D() {
510462
511463 const label = new SpriteText ( node . label ) as any
512464 label . color = '#e2e8f0'
513- label . textHeight = node . type === 'case' ? 6.2 : node . type === 'law' ? 5.8 : node . type === 'ai' ? 5.4 : node . type === 'person' ? 5 : 4.6
514- label . backgroundColor = isSelected ? 'rgba(15, 23, 42, 0.95)' : 'rgba(15, 23, 42, 0.88 )'
515- label . padding = [ 2.5 , 5 ]
465+ label . textHeight = node . type === 'case' ? 5.5 : node . type === 'law' ? 5 : node . type === 'ai' ? 4.5 : node . type === 'person' ? 4 : 3.5
466+ label . backgroundColor = 'rgba(15, 23, 42, 0.75 )'
467+ label . padding = [ 2 , 4 ]
516468 label . borderRadius = 3
517- label . position . y = size + 6
518- label . position . z = size * 0.45
519- if ( label . material ) {
520- label . material . depthTest = false
521- label . material . depthWrite = false
522- }
523- label . renderOrder = 1000
469+ label . position . y = - ( size + 6 )
524470 group . add ( label )
525471
526- if ( isStartNode ) {
527- const startTag = new SpriteText ( 'START' ) as any
528- startTag . color = '#0f172a'
529- startTag . textHeight = 4.2
530- startTag . backgroundColor = 'rgba(250, 204, 21, 0.98)'
531- startTag . padding = [ 2.5 , 5 ]
532- startTag . borderRadius = 3
533- startTag . position . y = size + 8
534- if ( startTag . material ) {
535- startTag . material . depthTest = false
536- startTag . material . depthWrite = false
537- }
538- startTag . renderOrder = 1001
539- group . add ( startTag )
540- }
541-
542472 return group
543- } , [ selectedNode ] )
473+ } , [ ] )
544474
545475 const linkColor = useCallback ( ( link : GraphLink ) => {
546- if ( selectedNode && ! isLinkConnectedToSelected ( link ) ) {
547- return 'rgba(100, 116, 139, 0.08)'
548- }
549476 switch ( link . type ) {
550- case 'SR_CONTAINS' : return 'rgba(59, 130, 246, 0.88 )'
551- case 'SR_REALIZED_BY' : return 'rgba(16, 185, 129, 0.88 )'
552- case 'SR_REFERENCES' : return 'rgba(139, 92, 246, 0.84 )'
553- case 'SR_SEQUENCE' : return 'rgba(34, 197, 94, 0.92 )'
554- case 'SR_BETRIFFT' : return 'rgba(244, 114, 182, 0.92 )'
555- case 'SR_GEHOERT_ZU' : return 'rgba(244, 114, 182, 0.84 )'
556- case 'SR_EINGEREICHT' : return 'rgba(251, 191, 36, 0.9 )'
557- case 'SR_FEHLT' : return 'rgba(239, 68, 68, 0.96 )'
558- case 'SR_HAT_PROBLEM' : return 'rgba(249, 115, 22, 0.94 )'
559- case 'SR_LOEST' : return 'rgba(34, 197, 94, 0.94 )'
560- case 'SR_COMPLIANT' : return 'rgba(6, 182, 212, 0.88 )'
561- case 'SR_UNTERSTUETZT' : return 'rgba(34, 197, 94, 0.88 )'
562- case 'SR_DEFINIERT_DURCH' : return 'rgba(99, 102, 241, 0.88 )'
563- case 'SR_EREIGNIS' : return 'rgba(168, 85, 247, 0.9 )'
564- case 'SR_DURCHLAEUFT' : return 'rgba(16, 185, 129, 0.9 )'
565- case 'SR_HAT' : return 'rgba(239, 68, 68, 0.84 )'
566- case 'SR_IN_AKTE' : return 'rgba(251, 191, 36, 0.84 )'
567- case 'SR_NACHWEIS' : return 'rgba(251, 191, 36, 0.9 )'
568- case 'SR_PRUEFT' : return 'rgba(239, 68, 68, 0.9 )'
569- case 'SR_APPLIES_TO' : return 'rgba(6, 182, 212, 0.84 )'
570- default : return 'rgba(148, 163, 184, 0.72 )'
477+ case 'SR_CONTAINS' : return 'rgba(59, 130, 246, 0.5 )'
478+ case 'SR_REALIZED_BY' : return 'rgba(16, 185, 129, 0.5 )'
479+ case 'SR_REFERENCES' : return 'rgba(139, 92, 246, 0.4 )'
480+ case 'SR_SEQUENCE' : return 'rgba(34, 197, 94, 0.6 )'
481+ case 'SR_BETRIFFT' : return 'rgba(244, 114, 182, 0.7 )'
482+ case 'SR_GEHOERT_ZU' : return 'rgba(244, 114, 182, 0.4 )'
483+ case 'SR_EINGEREICHT' : return 'rgba(251, 191, 36, 0.5 )'
484+ case 'SR_FEHLT' : return 'rgba(239, 68, 68, 0.8 )'
485+ case 'SR_HAT_PROBLEM' : return 'rgba(249, 115, 22, 0.7 )'
486+ case 'SR_LOEST' : return 'rgba(34, 197, 94, 0.8 )'
487+ case 'SR_COMPLIANT' : return 'rgba(6, 182, 212, 0.5 )'
488+ case 'SR_UNTERSTUETZT' : return 'rgba(34, 197, 94, 0.5 )'
489+ case 'SR_DEFINIERT_DURCH' : return 'rgba(99, 102, 241, 0.5 )'
490+ case 'SR_EREIGNIS' : return 'rgba(168, 85, 247, 0.6 )'
491+ case 'SR_DURCHLAEUFT' : return 'rgba(16, 185, 129, 0.6 )'
492+ case 'SR_HAT' : return 'rgba(239, 68, 68, 0.4 )'
493+ case 'SR_IN_AKTE' : return 'rgba(251, 191, 36, 0.3 )'
494+ case 'SR_NACHWEIS' : return 'rgba(251, 191, 36, 0.6 )'
495+ case 'SR_PRUEFT' : return 'rgba(239, 68, 68, 0.6 )'
496+ case 'SR_APPLIES_TO' : return 'rgba(6, 182, 212, 0.4 )'
497+ default : return 'rgba(148, 163, 184, 0.3 )'
571498 }
572- } , [ isLinkConnectedToSelected , selectedNode ] )
573-
574- const linkDirectionalArrowColor = useCallback ( ( link : GraphLink ) => {
575- if ( selectedNode && ! isLinkConnectedToSelected ( link ) ) {
576- return 'rgba(148, 163, 184, 0.2)'
577- }
578- return 'rgba(248, 250, 252, 0.98)'
579- } , [ isLinkConnectedToSelected , selectedNode ] )
580-
581- const linkWidth = useCallback ( ( link : GraphLink ) => {
582- if ( ! selectedNode ) return 3.4
583- return isLinkConnectedToSelected ( link ) ? 7.2 : 0.9
584- } , [ isLinkConnectedToSelected , selectedNode ] )
499+ } , [ ] )
585500
586501 const linkDirectionalParticles = useCallback ( ( link : GraphLink ) => {
587- if ( selectedNode && ! isLinkConnectedToSelected ( link ) ) return 0
588- return link . type === 'SR_SEQUENCE' ? 4
589- : link . type === 'SR_LOEST' ? 4
590- : link . type === 'SR_FEHLT' ? 3
591- : link . type === 'SR_HAT_PROBLEM' ? 3
592- : 2
593- } , [ isLinkConnectedToSelected , selectedNode ] )
594-
595- const linkThreeObject = useCallback ( ( link : GraphLink ) => {
596- const showLabel = ! ! selectedNode && isLinkConnectedToSelected ( link )
597- if ( ! showLabel ) return null
598-
599- const relationText = link . description && link . description . trim ( ) . length > 0
600- ? link . description
601- : link . type . replace ( 'SR_' , '' ) . replace ( / _ / g, ' ' )
602-
603- const label = new SpriteText ( relationText ) as any
604- label . color = '#f8fafc'
605- label . textHeight = 3.8
606- label . backgroundColor = 'rgba(15, 23, 42, 0.92)'
607- label . padding = [ 1.6 , 3.2 ]
608- label . borderRadius = 2
609- if ( label . material ) {
610- label . material . depthTest = false
611- label . material . depthWrite = false
612- }
613- label . renderOrder = 1000
614- return label
615- } , [ isLinkConnectedToSelected , selectedNode ] )
616-
617- const linkPositionUpdate = useCallback ( ( sprite : THREE . Object3D , coords : { start : { x : number ; y : number ; z : number } ; end : { x : number ; y : number ; z : number } } ) => {
618- const middlePos = {
619- x : coords . start . x + ( coords . end . x - coords . start . x ) * 0.5 ,
620- y : coords . start . y + ( coords . end . y - coords . start . y ) * 0.5 ,
621- z : coords . start . z + ( coords . end . z - coords . start . z ) * 0.5 ,
622- }
623- Object . assign ( sprite . position , middlePos )
502+ return link . type === 'SR_SEQUENCE' ? 3
503+ : link . type === 'SR_LOEST' ? 3
504+ : link . type === 'SR_FEHLT' ? 2
505+ : link . type === 'SR_HAT_PROBLEM' ? 2
506+ : 1
624507 } , [ ] )
625508
626509 // Build adjacency for detail panel
@@ -672,28 +555,27 @@ export function RELIEFKnowledgeGraph3D() {
672555 </ div >
673556
674557 { /* Legend */ }
675- < div className = "absolute bottom-3 left-3 z-20 bg-slate-900/90 backdrop-blur-sm rounded-lg p-5 border border-slate-700" >
676- < div className = "text-lg text-slate-100 font-bold mb-2" > Knotentypen</ div >
558+ < div className = "absolute bottom-3 left-3 z-20 bg-slate-900/90 backdrop-blur-sm rounded-lg p-3 border border-slate-700" >
559+ < div className = "text-xs text-slate-400 font-semibold mb-2" > Knotentypen</ div >
677560 < div className = "grid grid-cols-2 gap-x-4 gap-y-1" >
678561 { ( Object . keys ( NODE_LABELS ) as NodeType [ ] ) . map ( type => (
679562 < div key = { type } className = "flex items-center gap-1.5" >
680563 < span
681- className = "w-3 .5 h-3 .5 rounded-full flex-shrink-0"
564+ className = "w-2 .5 h-2 .5 rounded-full flex-shrink-0"
682565 style = { { backgroundColor : NODE_COLORS [ type ] } }
683566 />
684- < span className = "text-base text-slate-100 whitespace-nowrap" > { NODE_LABELS [ type ] } </ span >
567+ < span className = "text-[10px] text-slate-300 whitespace-nowrap" > { NODE_LABELS [ type ] } </ span >
685568 </ div >
686569 ) ) }
687570 </ div >
688- < div className = "mt-2 text-sm text-slate-300" > Pfeilspitze zeigt die Richtung der Beziehung.</ div >
689571 </ div >
690572
691573 { /* Stats */ }
692- < div className = "absolute top-3 left-3 z-20 bg-slate-900/90 backdrop-blur-sm rounded-lg px-4 py-3 border border-slate-700" >
693- < div className = "text-sm text-slate-200 " >
574+ < div className = "absolute top-3 left-3 z-20 bg-slate-900/90 backdrop-blur-sm rounded-lg px-3 py-2 border border-slate-700" >
575+ < div className = "text-[10px] text-slate-400 " >
694576 { graphData . nodes . length } Knoten · { graphData . links . length } Beziehungen
695577 </ div >
696- < div className = "text-sm text-blue-300 font-semibold " > RELIEF E-AKTE Knowledge Graph</ div >
578+ < div className = "text-[10px] text-blue-400 font-medium " > RELIEF E-AKTE Knowledge Graph</ div >
697579 </ div >
698580
699581 { /* Graph */ }
@@ -705,18 +587,14 @@ export function RELIEFKnowledgeGraph3D() {
705587 backgroundColor = "#0f172a"
706588 nodeThreeObject = { nodeThreeObject }
707589 onNodeClick = { handleNodeClick }
708- nodeThreeObjectExtend = { true }
709590 linkColor = { linkColor }
710- linkDirectionalArrowColor = { linkDirectionalArrowColor }
711- linkOpacity = { 0.98 }
712- linkWidth = { linkWidth }
713- linkThreeObject = { linkThreeObject }
714- linkPositionUpdate = { linkPositionUpdate }
715- linkDirectionalArrowLength = { 10 }
716- linkDirectionalArrowRelPos = { 0.94 }
591+ linkWidth = { 1.5 }
592+ linkOpacity = { 0.7 }
593+ linkDirectionalArrowLength = { 4 }
594+ linkDirectionalArrowRelPos = { 0.85 }
717595 linkDirectionalParticles = { linkDirectionalParticles }
718- linkDirectionalParticleWidth = { 4 }
719- linkDirectionalParticleSpeed = { 0.009 }
596+ linkDirectionalParticleWidth = { 2 }
597+ linkDirectionalParticleSpeed = { 0.005 }
720598 enableNodeDrag = { true }
721599 enableNavigationControls = { true }
722600 showNavInfo = { false }
0 commit comments