{"id":201,"date":"2026-02-11T17:24:23","date_gmt":"2026-02-11T10:24:23","guid":{"rendered":"https:\/\/www.e2connection.com\/?page_id=201"},"modified":"2026-02-11T20:56:37","modified_gmt":"2026-02-11T13:56:37","slug":"slab-on-pile","status":"publish","type":"page","link":"https:\/\/www.e2connection.com\/?page_id=201","title":{"rendered":"SLAB ON PILE"},"content":{"rendered":"\n<div id=\"slab-on-pile-root\"><\/div>\n\n<script src=\"https:\/\/unpkg.com\/react@18\/umd\/react.production.min.js\"><\/script>\n<script src=\"https:\/\/unpkg.com\/react-dom@18\/umd\/react-dom.production.min.js\"><\/script>\n<script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n\n<script>\n    const e = React.createElement;\n    const { useState, useMemo, useRef, useEffect } = React;\n\n    const HeatmapCanvas = ({ width, height, piles, maxLoad, startX, startY, spacing }) => {\n        const canvasRef = useRef(null);\n        const getColor = (t) => {\n            const stops = [{t:0, r:59, g:130, b:246}, {t:0.3, r:74, g:222, b:128}, {t:0.6, r:250, g:204, b:21}, {t:1, r:239, g:68, b:68}];\n            let low = stops[0], high = stops[stops.length-1];\n            for(let i=0; i<stops.length-1; i++) { if(t>=stops[i].t && t<=stops[i+1].t) { low=stops[i]; high=stops[i+1]; break; } }\n            const p = (t - low.t) \/ (high.t - low.t || 1);\n            return \"rgb(\" + Math.round(low.r+(high.r-low.r)*p) + \",\" + Math.round(low.g+(high.g-low.g)*p) + \",\" + Math.round(low.b+(high.b-low.b)*p) + \")\";\n        };\n        useEffect(() => {\n            const ctx = canvasRef.current.getContext('2d');\n            ctx.clearRect(0, 0, width, height);\n            const res = 5, sigma = spacing * 0.7, twoSigmaSq = 2 * sigma * sigma;\n            for(let x=0; x<width; x+=res) {\n                for(let y=0; y<height; y+=res) {\n                    let weight = 0;\n                    piles.forEach(p => {\n                        const dx = x-(startX+p.x_index*spacing), dy = y-(startY+p.y_index*spacing);\n                        weight += p.reaction * Math.exp(-(dx*dx+dy*dy)\/twoSigmaSq);\n                    });\n                    ctx.fillStyle = getColor(Math.min(1, weight\/(maxLoad * 1.05 || 1)));\n                    ctx.fillRect(x, y, res, res);\n                }\n            }\n        }, [width, height, piles, maxLoad, startX, startY, spacing]);\n        return e('canvas', { ref: canvasRef, width, height, className: 'absolute inset-0 w-full h-full opacity-60 rounded-[2rem]' });\n    };\n\n    const App = () => {\n        const [isManualLoad, setIsManualLoad] = useState(false);\n        const [manualFactoredLoad, setManualFactoredLoad] = useState(1000);\n        const [viewMode, setViewMode] = useState('diagram');\n        const [showTributary, setShowTributary] = useState(true);\n        const [spanX, setSpanX] = useState(4.0);\n        const [spanY, setSpanY] = useState(4.0);\n        const [numX, setNumX] = useState(3);\n        const [numY, setNumY] = useState(3);\n        const [thick, setThick] = useState(0.20);\n        const [liveLoad, setLiveLoad] = useState(300);\n        const [sdl, setSdl] = useState(100);\n        const [designMethod, setDesignMethod] = useState('sdm');\n        const [factorDL, setFactorDL] = useState(1.4);\n        const [factorLL, setFactorLL] = useState(1.7);\n\n        const results = useMemo(() => {\n            const sw = thick * 2400;\n            const dl = sw + sdl;\n            const currentDLFactor = designMethod === 'wsd' ? 1.0 : factorDL;\n            const currentLLFactor = designMethod === 'wsd' ? 1.0 : factorLL;\n            const calculatedLoad = (currentDLFactor * dl) + (currentLLFactor * liveLoad);\n            const factoredLoad = isManualLoad ? manualFactoredLoad : calculatedLoad;\n\n            let maxL = 0, minL = Infinity;\n            const piles = [];\n            for (let y = 0; y < numY; y++) {\n                for (let x = 0; x < numX; x++) {\n                    const tx = (x === 0 || x === numX - 1) ? spanX \/ 2 : spanX;\n                    const ty = (y === 0 || y === numY - 1) ? spanY \/ 2 : spanY;\n                    const r = tx * ty * factoredLoad;\n                    if (r > maxL) maxL = r; if (r < minL) minL = r;\n                    piles.push({ id: \"P-\" + (x+1) + String.fromCharCode(65+y), x_index: x, y_index: y, reaction: r });\n                }\n            }\n            return { factoredLoad, piles, maxLoad: maxL, minLoad: minL };\n        }, [isManualLoad, manualFactoredLoad, spanX, spanY, numX, numY, thick, liveLoad, sdl, designMethod, factorDL, factorLL]);\n\n        const vW = 800, vH = 700; \n        const spacing = Math.min(600 \/ Math.max(numX, 1), 500 \/ Math.max(numY, 1), 120);\n        const startX = (vW - (numX - 1) * spacing) \/ 2;\n        const startY = (vH - (numY - 1) * spacing) \/ 2;\n        const totalW = (numX - 1) * spanX;\n        const totalH = (numY - 1) * spanY;\n\n        return e('div', { className: 'max-w-7xl mx-auto p-4 lg:p-8 bg-white rounded-[2.5rem] shadow-2xl border' },\n            e('div', { className: 'grid grid-cols-1 lg:grid-cols-12 gap-8' },\n                \n                \/\/ Sidebar\n                e('div', { className: 'lg:col-span-4 space-y-4' },\n                    e('div', null, \n                        e('h1', { className: 'text-2xl font-black text-slate-900 leading-tight' }, 'Slab on Pile Calculator'), \n                        e('p', { className: 'text-blue-600 text-[10px] font-bold uppercase tracking-wider' }, 'Finite Element Contour (WSD \/ SDM)')\n                    ),\n                    \n                    e('div', { className: 'bg-slate-50 p-5 rounded-[1.5rem] border' },\n                        e('h2', { className: 'text-[10px] font-black text-slate-400 uppercase mb-3' }, '1. Grid Settings'),\n                        e('div', { className: 'grid grid-cols-2 gap-3' },\n                            e('div', null, e('label', { className: 'text-[9px] font-bold text-slate-500' }, 'SPAN X (m)'), e('input', { type:'number', step:'0.1', value:spanX, onChange:ev=>setSpanX(Number(ev.target.value)), className:'w-full p-2.5 border rounded-xl font-black text-slate-900 focus:ring-2 focus:ring-blue-500 outline-none' })),\n                            e('div', null, e('label', { className: 'text-[9px] font-bold text-slate-500' }, 'PILES X'), e('input', { type:'number', value:numX, onChange:ev=>setNumX(Number(ev.target.value)), className:'w-full p-2.5 border rounded-xl font-black text-slate-900 focus:ring-2 focus:ring-blue-500 outline-none' })),\n                            e('div', null, e('label', { className: 'text-[9px] font-bold text-slate-500' }, 'SPAN Y (m)'), e('input', { type:'number', step:'0.1', value:spanY, onChange:ev=>setSpanY(Number(ev.target.value)), className:'w-full p-2.5 border rounded-xl font-black text-slate-900 focus:ring-2 focus:ring-blue-500 outline-none' })),\n                            e('div', null, e('label', { className: 'text-[9px] font-bold text-slate-500' }, 'PILES Y'), e('input', { type:'number', value:numY, onChange:ev=>setNumY(Number(ev.target.value)), className:'w-full p-2.5 border rounded-xl font-black text-slate-900 focus:ring-2 focus:ring-blue-500 outline-none' }))\n                        )\n                    ),\n\n                    e('div', { className: 'bg-white p-5 rounded-[1.5rem] border shadow-sm' },\n                        e('div', { className: 'flex justify-between items-center mb-4 border-b pb-2' },\n                            e('h2', { className: 'text-[10px] font-black text-slate-400 uppercase' }, '2. Load & Factors'),\n                            e('button', { onClick: () => setIsManualLoad(!isManualLoad), className: \"px-3 py-1 text-[9px] font-black rounded-full \" + (isManualLoad ? 'bg-orange-500 text-white shadow' : 'bg-slate-100 text-slate-400') }, isManualLoad ? 'MANUAL' : 'AUTO')\n                        ),\n                        !isManualLoad ? e('div', { className: 'space-y-4' },\n                            e('div', { className: 'flex bg-slate-100 p-1 rounded-xl' },\n                                ['wsd', 'sdm'].map(m => e('button', { key:m, onClick:()=>setDesignMethod(m), className: \"flex-1 py-1.5 text-[10px] font-black rounded-lg transition-all \" + (designMethod===m?'bg-white shadow text-blue-600':'text-slate-400') }, m.toUpperCase()))\n                            ),\n                            designMethod === 'sdm' && e('div', { className: 'grid grid-cols-2 gap-3' },\n                                e('div', null, e('label', { className: 'text-[9px] font-black text-blue-500' }, 'FACTOR DL'), e('input', { type:'number', step:'0.1', value:factorDL, onChange:ev=>setFactorDL(Number(ev.target.value)), className:'w-full p-2 bg-blue-50 border border-blue-100 rounded-lg text-slate-900 font-bold' })),\n                                e('div', null, e('label', { className: 'text-[9px] font-black text-blue-500' }, 'FACTOR LL'), e('input', { type:'number', step:'0.1', value:factorLL, onChange:ev=>setFactorLL(Number(ev.target.value)), className:'w-full p-2 bg-blue-50 border border-blue-100 rounded-lg text-slate-900 font-bold' }))\n                            ),\n                            e('div', { className: 'grid grid-cols-2 gap-3' },\n                                e('div', null, e('label', { className: 'text-[9px] font-bold text-slate-400' }, 'LIVE LOAD'), e('input', { type:'number', value:liveLoad, onChange:ev=>setLiveLoad(Number(ev.target.value)), className:'w-full p-2 bg-slate-50 border rounded-lg font-black text-slate-900' })),\n                                e('div', null, e('label', { className: 'text-[9px] font-bold text-slate-400' }, 'SDL'), e('input', { type:'number', value:sdl, onChange:ev=>setSdl(Number(ev.target.value)), className:'w-full p-2 bg-slate-50 border rounded-lg font-black text-slate-900' }))\n                            ),\n                            e('div', null, e('label', { className: 'text-[9px] font-bold text-slate-500 uppercase' }, \"Thickness: \" + thick + \"m\"), e('input', { type:'range', min:0.1, max:0.5, step:0.01, value:thick, onChange:ev=>setThick(Number(ev.target.value)), className:'w-full h-1.5 mt-2 accent-blue-600 cursor-pointer' }))\n                        ) : e('div', { className: 'p-4 bg-orange-50 rounded-2xl border border-orange-200' },\n                            e('label', { className: 'text-[9px] font-black text-orange-600 uppercase mb-2 block' }, 'Override Load (kg\/m\u00b2)'),\n                            e('input', { type:'number', value:manualFactoredLoad, onChange:ev=>setManualFactoredLoad(Number(ev.target.value)), className:'w-full bg-transparent text-2xl font-black text-orange-700 outline-none' })\n                        )\n                    ),\n\n                    e('div', { className: 'bg-slate-900 p-6 rounded-[2rem] text-white shadow-xl' },\n                        e('p', { className: 'text-[10px] font-bold text-slate-500 mb-3 uppercase' }, 'Result Summary'),\n                        e('div', { className: 'flex justify-between border-b border-slate-800 pb-2 text-xs' }, e('span', null, 'Design Load:'), e('span', { className:'font-bold text-blue-400' }, Math.round(results.factoredLoad) + \" kg\/m\u00b2\")),\n                        e('div', { className: 'flex justify-between pt-3 text-xs' }, e('span', null, 'Max Pile Rx:'), e('span', { className:'text-2xl font-black text-red-500' }, (results.maxLoad\/1000).toFixed(2) + \" t\"))\n                    )\n                ),\n\n                \/\/ Visualization\n                e('div', { className: 'lg:col-span-8 flex flex-col min-h-[500px]' },\n                    e('div', { className: 'flex justify-between items-center mb-4 gap-2' },\n                        e('div', { className: 'flex bg-slate-100 p-1 rounded-xl' }, ['diagram', 'contour'].map(v => e('button', { key:v, onClick:()=>setViewMode(v), className: \"px-5 py-2 text-[10px] font-black rounded-lg transition-all \" + (viewMode===v?'bg-white shadow text-slate-900':'text-slate-400') }, v.toUpperCase()))),\n                        e('button', { onClick:()=>setShowTributary(!showTributary), className: \"px-4 py-2 text-[10px] font-black rounded-xl border transition-all \" + (showTributary?'bg-indigo-600 text-white shadow-md':'bg-white text-slate-400') }, 'TRIBUTARY')\n                    ),\n                    \n                    e('div', { className: 'relative flex-1 bg-slate-50 border border-slate-200 rounded-[3rem] overflow-hidden flex items-center justify-center' },\n                        \/\/ Title for Diagram (Added per request)\n                        e('div', { className: 'absolute top-6 left-1\/2 -translate-x-1\/2 z-20 pointer-events-none text-center' },\n                            e('p', { className: 'text-[11px] font-black text-slate-400 uppercase tracking-[0.3em]' }, 'Pile Load Diagram')\n                        ),\n\n                        viewMode === 'contour' && e(HeatmapCanvas, { width:vW, height:vH, piles:results.piles, maxLoad:results.maxLoad, startX, startY, spacing }),\n                        \n                        e('svg', { viewBox: \"0 0 \" + vW + \" \" + vH, preserveAspectRatio: \"xMidYMid meet\", className: \"w-full h-full p-8 relative z-10\" },\n                            \/\/ Dimension Labels\n                            e('g', { fill: \"#94a3b8\", fontSize: \"14\", fontWeight: \"bold\", textAnchor: \"middle\" },\n                                Array.from({ length: numX - 1 }).map((_, i) => e('text', { key: \"dx-\"+i, x: startX + i * spacing + spacing\/2, y: startY - 35 }, spanX.toFixed(2) + \"m\")),\n                                Array.from({ length: numY - 1 }).map((_, i) => e('text', { key: \"dy-\"+i, x: startX - 65, y: startY + i * spacing + spacing\/2, alignmentBaseline: \"middle\" }, spanY.toFixed(2) + \"m\"))\n                            ),\n                            \/\/ Grid Lines\n                            e('g', { stroke: \"#cbd5e1\", strokeWidth: 1, strokeDasharray: \"6,4\" },\n                                Array.from({ length: numX }).map((_, i) => e('line', { key: \"v-\"+i, x1: startX + i * spacing, y1: startY, x2: startX + i * spacing, y2: startY + (numY - 1) * spacing })),\n                                Array.from({ length: numY }).map((_, i) => e('line', { key: \"h-\"+i, x1: startX, y1: startY + i * spacing, x2: startX + (numX - 1) * spacing, y2: startY + i * spacing }))\n                            ),\n                            \/\/ Tributary Area\n                            showTributary && results.piles.map(p => {\n                                const cx = startX + p.x_index * spacing, cy = startY + p.y_index * spacing;\n                                let tw = spacing, th = spacing, tx = cx - spacing\/2, ty = cy - spacing\/2;\n                                if(p.x_index===0) { tx = cx; tw = spacing\/2; } else if(p.x_index===numX-1) { tw = spacing\/2; }\n                                if(p.y_index===0) { ty = cy; th = spacing\/2; } else if(p.y_index===numY-1) { th = spacing\/2; }\n                                return e('rect', { key:\"t-\"+p.id, x:tx, y:ty, width:tw, height:th, fill:'rgba(79, 70, 229, 0.02)', stroke:'#818cf8', strokeWidth:1, strokeDasharray:'4,2' });\n                            }),\n                            \/\/ Piles\n                            results.piles.map(p => {\n                                const cx = startX + p.x_index * spacing, cy = startY + p.y_index * spacing;\n                                const norm = (results.maxLoad - (results.minLoad || 0)) === 0 ? 1 : (p.reaction - results.minLoad) \/ (results.maxLoad - results.minLoad || 1);\n                                let s = '#22c55e', tCol = '#15803d', bgCol = '#f0fdf4';\n                                if(norm > 0.8) { s = '#ef4444'; tCol = '#b91c1c'; bgCol = '#fef2f2'; }\n                                else if(norm > 0.3) { s = '#eab308'; tCol = '#a16207'; bgCol = '#fffbeb'; }\n                                \n                                return e('g', { key:p.id },\n                                    e('text', { x:cx, y:cy-45, textAnchor:'middle', fontSize:11, fontWeight:900, fill:'#94a3b8' }, p.id),\n                                    e('circle', { cx, cy, r:35, fill:'white', stroke:s, strokeWidth:5, className: 'transition-all duration-300' }),\n                                    e('circle', { cx, cy, r:35, fill:bgCol, opacity:0.4 }),\n                                    e('text', { x:cx, y:cy+7, textAnchor:'middle', fontSize:16, fontWeight:900, fill:tCol }, (p.reaction\/1000).toFixed(2))\n                                );\n                            })\n                        ),\n                        \/\/ Bottom Info\n                        e('div', { className:'absolute bottom-6 left-1\/2 -translate-x-1\/2 bg-white\/90 backdrop-blur px-6 py-2 rounded-full border shadow-sm flex gap-4 text-[11px] font-black text-slate-600 uppercase tracking-widest' },\n                            e('span', null, \"Width: \" + totalW.toFixed(2) + \" m\"),\n                            e('span', { className:'text-slate-200' }, \"|\"),\n                            e('span', null, \"Length: \" + totalH.toFixed(2) + \" m\"),\n                            e('span', { className:'text-slate-200' }, \"|\"),\n                            e('span', { className:'text-blue-600' }, \"Total Area: \" + (totalW * totalH).toFixed(2) + \" m\u00b2\")\n                        )\n                    )\n                )\n            )\n        );\n    };\n\n    ReactDOM.createRoot(document.getElementById('slab-on-pile-root')).render(e(App));\n<\/script>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-basic","meta":{"footnotes":""},"class_list":["post-201","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.e2connection.com\/index.php?rest_route=\/wp\/v2\/pages\/201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.e2connection.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.e2connection.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.e2connection.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.e2connection.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=201"}],"version-history":[{"count":62,"href":"https:\/\/www.e2connection.com\/index.php?rest_route=\/wp\/v2\/pages\/201\/revisions"}],"predecessor-version":[{"id":326,"href":"https:\/\/www.e2connection.com\/index.php?rest_route=\/wp\/v2\/pages\/201\/revisions\/326"}],"wp:attachment":[{"href":"https:\/\/www.e2connection.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}