Files
anatomia/README.md
T

7.2 KiB

Atlas 3D de Anatomia

Plataforma web dockerizada para estudo de anatomia com um visualizador 3D interativo, camadas por sistema, dissecção virtual (plano de corte), busca/navegação por região e um modo quiz com repetição espaçada (SM-2).

Aviso importante sobre o conteúdo 3D

O dataset aberto BodyParts3D (lifesciencedb.jp/bp3d, CC BY-SA 2.1 Japan) não oferece um endpoint de download programável — os arquivos só são acessíveis por uma aplicação de visualização legada, exigindo download manual estrutura por estrutura. Por isso, o dataset semente incluído aqui (data-pipeline/seed/build-manifest.mjs) usa geometria paramétrica simples (caixas/esferas/cilindros) posicionada nas proporções e localizações anatômicas corretas de um corpo humano padrão — os nomes, sistemas, regiões e relações são anatomia real; só a malha 3D é esquemática, não fotorrealista.

A plataforma (frontend, backend, banco, Docker, todas as interações) está completa e pronta para receber malhas 3D reais. Para evoluir para segmentações reais do BodyParts3D (ou do projeto Z-Anatomy, que reempacota o mesmo dataset em Blender com nomes mais organizados), veja "Expandindo o dataset" abaixo — nenhum código do frontend/backend precisa mudar, só os arquivos .glb e o manifesto.

Arquitetura

Este compose foi adaptado para rodar como um stack separado dentro da infraestrutura existente do host cloud-lua-net, que já tem uma rede Docker externa dockernet e um container nginx central (com HTTP/3) que lê vhosts manuais em docker/nginx/sites/*.conf, mais um par nginx-gen + acme-companion que emite certificados Let's Encrypt via LETSENCRYPT_HOST.

container "nginx" (proxy principal do host, HTTP/3, já existente)
        │  vhost manual: docker/nginx/sites/30-atlas.conf
        │  proxy_pass → IP fixo do container anatomia-web em dockernet
        ▼
container "anatomia-web" (nginx interno deste projeto)
        ├─ serve o build estático do frontend (SPA)
        ├─ /api/*    → proxy → container "anatomia-api"
        └─ /models/* → proxy → container "anatomia-api"
container "anatomia-api" (Fastify + Prisma) ──▶ container "anatomia-db" (Postgres)

Não é publicada nenhuma porta no host — anatomia-web só é alcançável dentro da rede dockernet, no mesmo padrão já usado para outros apps desse compose (ex: frontend/backend do ticketz, nextcloud). Isso significa que este projeto roda como um docker compose próprio, independente do compose gigante do host — ele só precisa se conectar à mesma rede externa dockernet, o que já é suportado nativamente pelo Docker (containers de projetos Compose diferentes na mesma rede se enxergam normalmente).

Como rodar

# no host cloud-lua-net, dentro da pasta deste projeto (ex: /home/docker/anatomia)
cp .env.example .env
# Confirme que o IP escolhido está livre antes de subir:
docker network inspect dockernet | grep -A2 IPv4Address
# ajuste ANATOMIA_WEB_IP no .env se 10.15.0.93 já estiver em uso

docker compose up -d --build anatomia-db anatomia-api anatomia-web
docker compose run --rm anatomia-pipeline   # gera os modelos GLB semente e popula o banco

Depois, no host, copie deploy/nginx-vhost-atlas.conf para /home/docker/docker/nginx/sites/30-atlas.conf (ajustando o nome do arquivo para não colidir com os já existentes) e garanta que o DNS de atlas.martinsevieira.adv.br aponte para este servidor. O container anatomia-web já sobe com LETSENCRYPT_HOST=atlas.martinsevieira.adv.br, então o acme-companion existente no host emite o certificado automaticamente assim que o vhost estiver ativo e respondendo ao desafio ACME (veja os comentários no próprio arquivo deploy/nginx-vhost-atlas.conf para os detalhes/pré-requisitos).

Para reprocessar o dataset semente depois de editar data-pipeline/seed/build-manifest.mjs, rode docker compose run --rm anatomia-pipeline novamente.

Rodando fora desse host (dev local, sem "dockernet")

O docker-compose.yml deste projeto depende da rede externa dockernet e de um IP fixo, então para testar localmente em outra máquina crie a rede primeiro e ajuste/remova o ipv4_address, ou publique uma porta temporária no serviço anatomia-web, por exemplo:

docker network create dockernet   # numa máquina onde ela ainda não existe

E adicione temporariamente ao serviço anatomia-web no docker-compose.yml:

    ports:
      - "8080:80"

Depois docker compose up -d --build anatomia-db anatomia-api anatomia-web && docker compose run --rm anatomia-pipeline e acesse http://localhost:8080.

Estrutura do projeto

  • frontend/ — React + TypeScript + Vite + react-three-fiber (visualizador 3D), Zustand, Tailwind.
  • backend/ — Fastify + TypeScript + Prisma (API REST + arquivos .glb estáticos).
  • data-pipeline/ — scripts que geram os modelos 3D semente e populam o banco (roda como serviço Docker one-off, não fica sempre ligado).
  • nginx/nginx.conf — nginx interno que serve o frontend e faz proxy para a API.

Funcionalidades

  • Camadas por sistema: esquelético, muscular, nervoso, cardiovascular, respiratório, tegumentar — ligar/desligar independentemente.
  • Labels clicáveis: clique em qualquer estrutura no modelo 3D para ver nome, sistema, região e descrição.
  • Busca e navegação: busca fuzzy + árvore por sistema/região; selecionar uma estrutura move a câmera até ela.
  • Dissecção virtual: plano de corte deslizante nos três planos anatômicos (sagital, coronal, transversal).
  • Módulo de planos e eixos anatômicos (/planos-anatomicos): manequim simples com os três planos de secção, eixos de direção rotulados e glossário de termos (anterior/posterior, medial/lateral, proximal/distal etc.).
  • Quiz com repetição espaçada (/quiz): pede para localizar a estrutura no modelo 3D; usa o algoritmo SM-2 para agendar revisões.

Expandindo o dataset

O schema (backend/prisma/schema.prisma) já suporta qualquer sistema anatômico adicional (digestório, urinário, endócrino, reprodutor, linfático, sentidos) — basta adicionar dados, sem mudar código:

  1. Estruturas novas com geometria esquemática: edite data-pipeline/seed/build-manifest.mjs, adicione entradas com add(...)/addBilateral(...) e rode o pipeline novamente.
  2. Malhas 3D reais (BodyParts3D/Z-Anatomy): exporte os .obj desejados (manualmente pelo visualizador do BodyParts3D, ou do projeto Blender Z-Anatomy), converta para .glb (obj2gltf ou exportação direta do Blender), e substitua a geração procedural daquela estrutura por esse arquivo real — nomeie o node/mesh igual ao slug já usado no manifesto para que clique, quiz e busca continuem funcionando sem alterações de código.

Desenvolvimento local (sem Docker)

# Backend
cd backend && npm install
export DATABASE_URL=postgresql://anatomia:anatomia@localhost:5432/anatomia
npx prisma migrate deploy
npm run dev

# Frontend (em outro terminal)
cd frontend && npm install
npm run dev   # http://localhost:5173, faz proxy de /api e /models para :3333

# Dataset semente (em outro terminal, com DATABASE_URL exportada)
cd data-pipeline && npm install
npm run build:seed-models
npm run seed:db