first commit
This commit is contained in:
commit
0e854110d3
49 files changed
+2292
No files matched your search
@@ -0,0 +1,103 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
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`:
|
||||
|
||||
```yaml
|
||||
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)
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
Reference in new issue
Block a user