From efb57d9e38709e472848f0c9b266cbcf59e336d2 Mon Sep 17 00:00:00 2001 From: Rodrigo Bertoldo de Sousa Martins Date: Thu, 17 Sep 2026 12:39:56 -0300 Subject: [PATCH] mitose e meiose interfase Signed-off-by: Rodrigo Bertoldo de Sousa Martins --- .../cellDivision/CellDivisionScene.tsx | 61 +++++++++---- frontend/src/data/cellDivisionStages.ts | 85 +++++++++++++++++-- 2 files changed, 123 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/cellDivision/CellDivisionScene.tsx b/frontend/src/components/cellDivision/CellDivisionScene.tsx index cce7981..2a3cb7f 100644 --- a/frontend/src/components/cellDivision/CellDivisionScene.tsx +++ b/frontend/src/components/cellDivision/CellDivisionScene.tsx @@ -75,7 +75,8 @@ interface CellSlotState { position: THREE.Vector3; radius: { value: number }; envelope: { value: number }; - spindle: { value: number }; + centrosomes: { value: number }; + fibers: { value: number }; elongated: { value: number }; } @@ -83,27 +84,41 @@ function AnimatedCellSlot({ target, state, }: { - target: { center: [number, number, number]; radius: number; envelope: number; spindle: boolean; elongated: number } | null; + target: { + center: [number, number, number]; + radius: number; + envelope: number; + spindle: boolean; + centrosomes?: boolean; + elongated: number; + } | null; state: CellSlotState; }) { const groupRef = useRef(null); const membraneRef = useRef(null); const membraneMatRef = useRef(null); const envelopeMatRef = useRef(null); - const spindleRef = useRef(null); + const centrosomesRef = useRef(null); + const fibersRef = useRef(null); useFrame((_, delta) => { const k = smoothing(delta); const targetPos = target ? new THREE.Vector3(...target.center) : state.position.clone(); const targetRadius = target ? target.radius : 0; const targetEnvelope = target ? target.envelope : 0; - const targetSpindle = target?.spindle ? 1 : 0; + const targetFibers = target?.spindle ? 1 : 0; + // Centrossomos ficam visíveis tanto na G2 (só eles, terminando de se + // preparar) quanto durante o fuso de verdade (prófase em diante) — + // `spindle: true` já implica centrossomos visíveis, sem precisar + // repetir `centrosomes: true` em cada estágio. + const targetCentrosomes = target?.spindle || target?.centrosomes ? 1 : 0; const targetElongated = target ? target.elongated : 0; state.position.lerp(targetPos, k); state.radius.value = THREE.MathUtils.lerp(state.radius.value, targetRadius, k); state.envelope.value = THREE.MathUtils.lerp(state.envelope.value, targetEnvelope, k); - state.spindle.value = THREE.MathUtils.lerp(state.spindle.value, targetSpindle, k); + state.centrosomes.value = THREE.MathUtils.lerp(state.centrosomes.value, targetCentrosomes, k); + state.fibers.value = THREE.MathUtils.lerp(state.fibers.value, targetFibers, k); state.elongated.value = THREE.MathUtils.lerp(state.elongated.value, targetElongated, k); if (groupRef.current) groupRef.current.position.copy(state.position); @@ -114,8 +129,14 @@ function AnimatedCellSlot({ } if (membraneMatRef.current) membraneMatRef.current.opacity = Math.min(0.22, state.radius.value * 0.28); if (envelopeMatRef.current) envelopeMatRef.current.opacity = state.envelope.value * 0.35; - if (spindleRef.current) spindleRef.current.visible = state.spindle.value > 0.05; - if (spindleRef.current) spindleRef.current.scale.setScalar(state.spindle.value); + if (centrosomesRef.current) { + centrosomesRef.current.visible = state.centrosomes.value > 0.05; + centrosomesRef.current.scale.setScalar(state.centrosomes.value); + } + if (fibersRef.current) { + fibersRef.current.visible = state.fibers.value > 0.05; + fibersRef.current.scale.setScalar(state.fibers.value); + } }); return ( @@ -137,18 +158,25 @@ function AnimatedCellSlot({ - {/* fuso mitótico: 2 centrossomos + fibras finas em leque */} - + {/* Centrossomos — visíveis sozinhos na G2 (recém-duplicados, ainda + sem fibra nenhuma) e continuam visíveis junto do fuso a partir + da prófase. */} + {[-1, 1].map((side) => ( - - - - - + + + + + ))} + + {/* fibras do fuso — só a partir da prófase (quando `spindle: true`) */} + + {[-1, 1].map((side) => ( + {[-0.25, -0.1, 0.1, 0.25].map((offset, i) => ( 0 ? Math.PI / 2 + offset * 0.3 : -Math.PI / 2 + offset * 0.3]} > @@ -172,7 +200,8 @@ export function CellDivisionScene({ stage }: { stage: Stage }) { position: new THREE.Vector3(0, 0, 0), radius: { value: 0 }, envelope: { value: 0 }, - spindle: { value: 0 }, + centrosomes: { value: 0 }, + fibers: { value: 0 }, elongated: { value: 0 }, })), [], diff --git a/frontend/src/data/cellDivisionStages.ts b/frontend/src/data/cellDivisionStages.ts index 2dd5712..fa0d4ce 100644 --- a/frontend/src/data/cellDivisionStages.ts +++ b/frontend/src/data/cellDivisionStages.ts @@ -28,7 +28,11 @@ export interface CellTarget { center: [number, number, number]; radius: number; envelope: number; // opacidade do envelope nuclear (0 = dissolvido, 1 = intacto) - spindle: boolean; // mostra fuso mitótico (centrossomos + fibras) neste estágio + spindle: boolean; // mostra o fuso mitótico completo (centrossomos + fibras) neste estágio + // Mostra só os 2 centrossomos, sem fibras — a duplicação deles termina + // na G2, antes do fuso de verdade se formar na prófase. Opcional porque + // só a G2 precisa disso; `spindle: true` já implica centrossomos visíveis. + centrosomes?: boolean; elongated: number; // 0 = esférica, 1 = alongada com sulco de clivagem (citocinese em andamento) } @@ -62,6 +66,21 @@ function single(id: string, color: string, cell: number, pos: [number, number, n return { id, color, cell, pos, rot }; } +// Cromossomo AINDA NÃO duplicado (G1, antes da fase S): as duas +// cromátides-irmãs existem como entidades (o sistema de animação espera +// as 8 IDs em todo estágio — ver CellDivisionScene.tsx), mas ficam na +// MESMA posição E MESMA rotação, uma exatamente em cima da outra — +// visualmente indistinguíveis de um cromossomo único. Quando o estágio +// seguinte (fase S) muda a rotação da cromátide "b" pra 180°, ela +// "gira pra fora" de trás da outra — a duplicação do DNA acontecendo +// diante dos olhos, não só descrita no texto. +function unduplicated(idA: string, idB: string, color: string, cell: number, pos: [number, number, number]): ChromatidTarget[] { + return [ + { id: idA, color, cell, pos, rot: 0 }, + { id: idB, color, cell, pos, rot: 0 }, + ]; +} + // ============================= MITOSE =================================== // As 4 cromátides-irmãs (uma de cada cromossomo) vão pro polo A, as outras // 4 pro polo B — as duas células-filhas ficam geneticamente IDÊNTICAS à @@ -69,11 +88,37 @@ function single(id: string, color: string, cell: number, pos: [number, number, n export const MITOSIS_STAGES: Stage[] = [ { - id: "interfase", - label: "Interfase", + id: "interfase-g1", + label: "Interfase — G1", description: - "A célula não está se dividindo: cresce e, na fase S, duplica todo o seu DNA. Os cromossomos já estão duplicados, mas ainda descondensados (finos, dispersos) — por isso não aparecem como bastões nítidos ainda.", + "A célula recém-formada cresce e funciona normalmente. Cada cromossomo ainda tem só 1 cromátide (não duplicado) — é o estado em que a célula passa a maior parte da vida, antes de se preparar pra dividir.", cells: [{ center: [0, 0, 0], radius: R, envelope: 1, spindle: false, elongated: 0 }], + chromatids: [ + ...unduplicated("b1a", "b1b", COLOR_B, 0, [-0.28, 0.22, 0.1]), + ...unduplicated("c1a", "c1b", COLOR_C, 0, [0.05, 0.3, -0.15]), + ...unduplicated("o1a", "o1b", COLOR_O, 0, [0.25, -0.15, 0.2]), + ...unduplicated("y1a", "y1b", COLOR_Y, 0, [-0.1, -0.28, -0.1]), + ], + }, + { + id: "interfase-s", + label: "Interfase — Fase S", + description: + "O momento-chave da interfase: na fase S (\"síntese\"), a célula duplica TODO o seu DNA — cada cromossomo passa a ter 2 cromátides-irmãs idênticas, unidas pelo centrômero (o \"X\"). Sem essa duplicação, a mitose não teria DNA suficiente pra dar 1 cópia completa a cada célula-filha. Os cromossomos continuam descondensados (finos, dispersos) — ainda não dá pra vê-los como bastões nítidos.", + cells: [{ center: [0, 0, 0], radius: R, envelope: 1, spindle: false, elongated: 0 }], + chromatids: [ + ...pair("b1a", "b1b", COLOR_B, 0, [-0.28, 0.22, 0.1]), + ...pair("c1a", "c1b", COLOR_C, 0, [0.05, 0.3, -0.15]), + ...pair("o1a", "o1b", COLOR_O, 0, [0.25, -0.15, 0.2]), + ...pair("y1a", "y1b", COLOR_Y, 0, [-0.1, -0.28, -0.1]), + ], + }, + { + id: "interfase-g2", + label: "Interfase — G2", + description: + "A célula continua crescendo e confere/repara o DNA recém-duplicado antes de seguir em frente — se o DNA estiver com erro grave demais pra corrigir, a divisão pode ser interrompida aqui. É também na G2 que os centrossomos (já duplicados) terminam de se preparar — por isso aparecem 2 pela primeira vez, ainda sem fibras.", + cells: [{ center: [0, 0, 0], radius: R, envelope: 1, spindle: false, centrosomes: true, elongated: 0 }], chromatids: [ ...pair("b1a", "b1b", COLOR_B, 0, [-0.28, 0.22, 0.1]), ...pair("c1a", "c1b", COLOR_C, 0, [0.05, 0.3, -0.15]), @@ -186,11 +231,37 @@ export const MITOSIS_STAGES: Stage[] = [ export const MEIOSIS_STAGES: Stage[] = [ { - id: "interfase", - label: "Interfase", + id: "interfase-g1", + label: "Interfase — G1", description: - "Igual à mitose: a célula duplica todo o seu DNA na fase S. Os cromossomos já duplicados continuam descondensados.", + "Igual à mitose: a célula cresce e funciona normalmente, com cada cromossomo ainda numa única cromátide (não duplicado).", cells: [{ center: [0, 0, 0], radius: R, envelope: 1, spindle: false, elongated: 0 }], + chromatids: [ + ...unduplicated("b1a", "b1b", COLOR_B, 0, [-0.28, 0.22, 0.1]), + ...unduplicated("c1a", "c1b", COLOR_C, 0, [0.05, 0.3, -0.15]), + ...unduplicated("o1a", "o1b", COLOR_O, 0, [0.25, -0.15, 0.2]), + ...unduplicated("y1a", "y1b", COLOR_Y, 0, [-0.1, -0.28, -0.1]), + ], + }, + { + id: "interfase-s", + label: "Interfase — Fase S", + description: + "Igual à mitose: na fase S, a célula duplica TODO o seu DNA antes de entrar em meiose — cada cromossomo passa a ter 2 cromátides-irmãs. Isso é o que permite que, mesmo depois de DUAS divisões (Meiose I e II), cada gameta final ainda receba 1 cromátide completa. Os cromossomos continuam descondensados por enquanto.", + cells: [{ center: [0, 0, 0], radius: R, envelope: 1, spindle: false, elongated: 0 }], + chromatids: [ + ...pair("b1a", "b1b", COLOR_B, 0, [-0.28, 0.22, 0.1]), + ...pair("c1a", "c1b", COLOR_C, 0, [0.05, 0.3, -0.15]), + ...pair("o1a", "o1b", COLOR_O, 0, [0.25, -0.15, 0.2]), + ...pair("y1a", "y1b", COLOR_Y, 0, [-0.1, -0.28, -0.1]), + ], + }, + { + id: "interfase-g2", + label: "Interfase — G2", + description: + "Igual à mitose: a célula confere/repara o DNA duplicado e termina de preparar os centrossomos (já duplicados, por isso aparecem 2 pela primeira vez) antes de entrar na Prófase I.", + cells: [{ center: [0, 0, 0], radius: R, envelope: 1, spindle: false, centrosomes: true, elongated: 0 }], chromatids: [ ...pair("b1a", "b1b", COLOR_B, 0, [-0.28, 0.22, 0.1]), ...pair("c1a", "c1b", COLOR_C, 0, [0.05, 0.3, -0.15]),