AI-powered structural integrity analyzer for 3D models. Upload any .stl file and get an instant integrity score, geometric metrics, and natural-language improvement feedback — all in the browser.
Live site: structai.vercel.app · API: structai-production.up.railway.app
- Structural score — ML model trained on hundreds of meshes outputs a 0–1 integrity score
- Mesh metrics — volume, surface area, triangle/vertex count, bounding box, aspect ratio, watertight check, normal consistency, Euler number
- AI feedback — GPT-4o-mini generates concise, data-driven improvement recommendations
- Interactive 3D viewer — Three.js renderer lets you rotate and inspect the model in the browser
- Auth — Clerk-powered sign-in/sign-up, required before uploading
| Layer | Tech |
|---|---|
| Frontend | React 19, Vite, React Router |
| Auth | Clerk |
| 3D rendering | Three.js |
| Backend | Flask, Gunicorn |
| ML | scikit-learn (Gradient Boosting), trained on synthetic mesh dataset |
| Mesh processing | trimesh |
| AI feedback | OpenAI API (gpt-4o-mini) |
| Frontend hosting | Vercel |
| Backend hosting | Railway |
structai/
├── src/
│ ├── pages/
│ │ ├── Home.jsx # Landing page with preview + about sections
│ │ ├── Upload.jsx # File upload, analysis progress, results view
│ │ ├── About.jsx # Standalone about page
│ │ └── Auth.jsx # Clerk sign-in/sign-up
│ ├── components/
│ │ ├── Navbar.jsx
│ │ └── STLViewer.jsx # Three.js STL renderer
│ └── assets/
├── python-service/
│ ├── app.py # Flask API (/analyze, /health)
│ ├── features.py # trimesh feature extraction
│ ├── train_model.py # Model training script
│ ├── generate_dataset.py # Synthetic dataset generation
│ ├── model.joblib # Trained scikit-learn model
│ ├── requirements.txt
│ └── Procfile
└── public/
- Node.js 18+
- Python 3.10+
npm install
npm run devRuns at http://localhost:5173.
cd python-service
pip install -r requirements.txt
python app.pyRuns at http://localhost:5000.
Create python-service/.env:
OPENAI_API_KEY=your_openai_keyCreate .env.local in the project root:
VITE_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
VITE_API_URL=http://localhost:5000Set the following environment variables in your Vercel project settings:
| Variable | Value |
|---|---|
VITE_CLERK_PUBLISHABLE_KEY |
Your Clerk publishable key |
VITE_API_URL |
Your Railway backend URL (no trailing slash) |
Set the following environment variables in your Railway service:
| Variable | Value |
|---|---|
OPENAI_API_KEY |
Your OpenAI API key |
The Procfile configures gunicorn automatically. Railway injects PORT at runtime.
The model is a scikit-learn pipeline trained on a synthetic dataset of 3D meshes with known structural properties. Features include volume, surface area, triangle count, aspect ratio, sphericity, normal consistency, and watertight status. The output is a continuous score from 0 (structurally weak) to 1 (excellent integrity).
To retrain:
cd python-service
python generate_dataset.py # regenerate training data
python train_model.py # retrain and save model.joblibThe integrity score is a continuous value from 0.0 (structurally weak) to 1.0 (excellent). Scores are produced by a GradientBoostingRegressor trained to approximate the following deterministic engineering formula, which was used to label the synthetic training dataset.
score = 0.25 (baseline)
+ watertight bonus (up to +0.25)
+ normal consistency (+0.05)
+ topology bonus (+0.05)
+ sphericity reward (up to +0.40)
− aspect ratio penalty (up to −0.25)
+ noise (σ = 0.015, training only)
Baseline — +0.25
Every mesh starts here regardless of quality.
Watertight — +0.25
A watertight mesh has no holes, gaps, or open edges — every edge is shared by exactly two faces. This is the single largest factor. A non-watertight mesh (open shell, missing faces) receives no bonus and also disqualifies the sphericity reward.
Consistent normals — +0.05
All face normals must wind in a consistent direction (all outward or all inward). Inconsistent winding indicates inverted faces, which causes rendering and manufacturing defects.
Euler number == 2 — +0.05
The Euler characteristic V − E + F = 2 holds for any topologically valid closed surface (genus 0, like a sphere or a box). Tori score 0 here (Euler = 0) due to their hole. Corrupted or degenerate meshes often produce unexpected Euler numbers.
Sphericity — up to +0.40
Sphericity measures how close a shape's surface-to-volume ratio is to that of a perfect sphere:
sphericity = (π^(1/3) × (6V)^(2/3)) / A
Where V is volume and A is surface area. A perfect sphere scores 1.0, earning the full +0.40. Flat slabs, thin rods, and hollow shells approach 0. Only applied when the mesh is watertight (volume is meaningful).
Aspect ratio penalty — up to −0.25
Computed as max_extent / min_extent across the bounding box axes. A perfect cube has aspect ratio 1 (no penalty). The penalty scales as:
penalty = min(0.25, (aspect_ratio − 1) × 0.025)
This reaches its cap of −0.25 at an aspect ratio of 11 (e.g. a rod 11× longer than it is wide).
A perfect sphere achieves the theoretical maximum:
| Component | Value |
|---|---|
| Baseline | +0.25 |
| Watertight | +0.25 |
| Consistent normals | +0.05 |
| Euler number == 2 | +0.05 |
| Sphericity (= 1.0) | +0.40 |
| Aspect ratio (= 1.0) | −0.00 |
| Total | 1.00 |
The GradientBoostingRegressor (300 estimators, learning rate 0.05, max depth 4) is trained on 987 synthetic meshes across six categories:
| Category | Count | Purpose |
|---|---|---|
| Intact primitives | 622 | Boxes, cylinders, spheres, cones, tori, capsules |
| Corrupted (face removal) | 120 | Non-watertight meshes with random holes |
| Winding-inconsistent | 140 | Watertight meshes with 8–50% of faces flipped — the only source of is_winding_consistent = 0 in the dataset |
| Multi-component | 26 | Two or three separate primitives concatenated — Euler = 4 or 6 |
| Open shells / extra tori | 79 | Capless cylinders, hemispheres, extended tori grid — varied Euler numbers and non-watertight topology |
Rather than applying the formula directly at inference time, the model learns non-linear interactions between features — for example, how SA/V ratio and aspect ratio together predict structural weakness in ways the formula alone doesn't fully capture. The final score is clipped to [0.0, 1.0].
Feature importances (from last training run):
| Feature | Importance |
|---|---|
| sphericity | 0.7336 |
| is_watertight | 0.1817 |
| aspect_ratio | 0.0602 |
| volume | 0.0141 |
| euler_number | 0.0036 |
| is_winding_consistent | 0.0032 |
| triangle_count | 0.0012 |
| avg_edge_length | 0.0009 |
| surface_area | 0.0007 |
| sa_v_ratio | 0.0005 |
| vertex_count | 0.0004 |
| Range | Label |
|---|---|
| 0.70 – 1.00 | Strong structural integrity |
| 0.40 – 0.69 | Moderate — may need improvements |
| 0.00 – 0.39 | Weak — significant issues detected |