01 - Quick Start (10 minutes)
Get CAD/CAM simulation running in your existing Next.js app
Step 1: Install Dependencies (2 min)
cd core
npm install three @react-three/fiber @react-three/drei
That's all! These are the only new packages needed.
Step 2: Create Folder Structure (1 min)
# Create the demo page folder
mkdir -p src/app/(core)/cad-cam-demo/components
mkdir -p src/app/(core)/cad-cam-demo/utils
mkdir -p src/lib/cad
Step 3: Create Types File (2 min)
Create src/app/(core)/cad-cam-demo/utils/types.ts:
// Water quality sensor data (simulated)
export interface SensorData {
pH: number;
BOD: number;
COD: number;
TSS: number;
TDS: number;
flowRate: number;
temperature: number;
}
// ML prediction output
export interface MLPrediction {
reusabilityClass: "A" | "B" | "C" | "D" | "E";
treatmentStage: "primary" | "secondary" | "tertiary";
confidence: number;
}
// Design parameters calculated from ML
export interface DesignParams {
tankDiameter: number; // meters
tankHeight: number; // meters
tankVolume: number; // m³
inletDiameter: number; // mm
outletDiameter: number; // mm
baffleCount: number;
aerationSlots: number;
wallThickness: number; // mm
}
// G-code for CNC simulation
export interface GCodeLine {
command: string;
x?: number;
y?: number;
z?: number;
f?: number; // feed rate
}
export type SimulationStatus = "idle" | "running" | "paused" | "complete";
Step 4: Create Design Calculator (3 min)
Create src/app/(core)/cad-cam-demo/utils/design-calculator.ts:
import { SensorData, DesignParams, MLPrediction } from "./types";
/**
* Convert ML prediction + sensor data → CAD design parameters
* This is the core logic that connects ML to CAD/CAM
*/
export function calculateDesignParams(sensors: SensorData, prediction: MLPrediction): DesignParams {
// Retention time based on treatment stage
const retentionHours = {
primary: 2,
secondary: 6,
tertiary: 8,
}[prediction.treatmentStage];
// Calculate tank volume (flow rate × retention time)
const tankVolume = sensors.flowRate * retentionHours;
// Optimal height-to-diameter ratio is ~2:1
const diameter = Math.pow((tankVolume * 4) / (Math.PI * 2), 1 / 3);
const height = diameter * 2;
// Inlet/outlet sizing based on flow rate (target velocity: 1.5 m/s)
const pipeArea = sensors.flowRate / 3600 / 1.5; // m²
const pipeDiameter = Math.sqrt((pipeArea * 4) / Math.PI) * 1000; // mm
// Baffles based on BOD level
const baffleCount = sensors.BOD > 300 ? 6 : sensors.BOD > 200 ? 4 : 2;
// Aeration slots based on treatment stage
const aerationSlots = prediction.treatmentStage === "tertiary" ? 12 : prediction.treatmentStage === "secondary" ? 8 : 4;
// Wall thickness based on volume (simplified)
const wallThickness = Math.max(6, Math.round(tankVolume / 10));
return {
tankDiameter: Math.round(diameter * 100) / 100,
tankHeight: Math.round(height * 100) / 100,
tankVolume: Math.round(tankVolume * 10) / 10,
inletDiameter: Math.round(pipeDiameter),
outletDiameter: Math.round(pipeDiameter),
baffleCount,
aerationSlots,
wallThickness: Math.min(wallThickness, 20),
};
}
/**
* Generate simple G-code for tank outline (2D profile)
* This simulates what would go to a CNC machine
*/
export function generateTankGCode(params: DesignParams): string {
const lines: string[] = [
"; Tank Profile G-code (Simulated)",
"; Generated by Edubotx CAD/CAM",
`; Tank: Ø${params.tankDiameter}m × ${params.tankHeight}m`,
"",
"G21 ; Metric",
"G90 ; Absolute positioning",
"G17 ; XY plane",
"",
"; Move to start position",
"G0 Z5",
`G0 X0 Y${(params.tankDiameter * 500).toFixed(1)}`,
"",
"; Cut tank profile (circle)",
"G1 Z-2 F500",
`G2 X0 Y${(params.tankDiameter * 500).toFixed(1)} I0 J${(-params.tankDiameter * 500).toFixed(1)} F1000`,
"",
"; Retract",
"G0 Z5",
"G0 X0 Y0",
"",
"M30 ; End program",
];
return lines.join("\n");
}
Step 5: Create Sensor Simulator (2 min)
Create src/lib/cad/simulator.ts:
import { SensorData } from "@/app/(core)/cad-cam-demo/utils/types";
/**
* Simulates water quality sensor readings
* Uses same pattern as adaptive-optimizers generateParams
*/
export function generateSensorData(
progress: number, // 0-1
scenario: "normal" | "polluted" | "clean" = "normal"
): SensorData {
const noise = () => (Math.random() - 0.5) * 0.1;
const scenarios = {
normal: {
pH: { min: 6.8, max: 7.5 },
BOD: { min: 150, max: 250 },
COD: { min: 300, max: 500 },
TSS: { min: 100, max: 200 },
TDS: { min: 500, max: 800 },
flowRate: { min: 80, max: 120 },
temperature: { min: 25, max: 35 },
},
polluted: {
pH: { min: 5.5, max: 6.5 },
BOD: { min: 350, max: 500 },
COD: { min: 700, max: 1000 },
TSS: { min: 250, max: 400 },
TDS: { min: 1000, max: 1500 },
flowRate: { min: 60, max: 100 },
temperature: { min: 30, max: 40 },
},
clean: {
pH: { min: 7.0, max: 7.8 },
BOD: { min: 50, max: 100 },
COD: { min: 100, max: 200 },
TSS: { min: 30, max: 80 },
TDS: { min: 300, max: 500 },
flowRate: { min: 100, max: 150 },
temperature: { min: 20, max: 28 },
},
};
const s = scenarios[scenario];
const lerp = (range: { min: number; max: number }) => range.min + (range.max - range.min) * progress * (1 + noise());
return {
pH: parseFloat(lerp(s.pH).toFixed(1)),
BOD: Math.round(lerp(s.BOD)),
COD: Math.round(lerp(s.COD)),
TSS: Math.round(lerp(s.TSS)),
TDS: Math.round(lerp(s.TDS)),
flowRate: Math.round(lerp(s.flowRate)),
temperature: Math.round(lerp(s.temperature)),
};
}
/**
* Mock ML API call (when real API isn't available)
*/
export function mockMLPrediction(sensors: SensorData) {
// Simple rule-based prediction for demo
let reusabilityClass: "A" | "B" | "C" | "D" | "E";
let treatmentStage: "primary" | "secondary" | "tertiary";
if (sensors.BOD < 100 && sensors.COD < 200) {
reusabilityClass = "A";
treatmentStage = "primary";
} else if (sensors.BOD < 200 && sensors.COD < 400) {
reusabilityClass = "B";
treatmentStage = "secondary";
} else if (sensors.BOD < 300 && sensors.COD < 600) {
reusabilityClass = "C";
treatmentStage = "secondary";
} else if (sensors.BOD < 400) {
reusabilityClass = "D";
treatmentStage = "tertiary";
} else {
reusabilityClass = "E";
treatmentStage = "tertiary";
}
return {
reusabilityClass,
treatmentStage,
confidence: 0.85 + Math.random() * 0.1,
};
}
Verify Setup
Your folder structure should now look like:
src/
├── app/(core)/cad-cam-demo/
│ └── utils/
│ ├── types.ts ✅
│ └── design-calculator.ts ✅
└── lib/cad/
└── simulator.ts ✅
Next: 02-SENSOR-SIMULATION.md
Build the sensor simulator component →