3D, Plotting, Drawing¶
CalcpadCE pairs symbolic engineering calculations with browser-rendered figures, so the same worksheet computes and illustrates the result. Drawings, plots and 3D models are generated from the same inputs as the calculations, so changing a dimension or load updates the figures and the report consistently โ no separate CAD or charting tool is needed in the loop.
Four complementary techniques cover most engineering-reporting needs: native 2D plots via the $Plot and $Map directives for line graphs and contour maps, parametric SVG drawings assembled from reusable #def macros for annotated reinforced-concrete cross-sections and structural details, embedded glTF models via Google's <model-viewer> for rotating CAD previews, and fully interactive surfaces powered by Plotly.js or three.js when pan, zoom or animation is needed.
Each example pairs the worksheet source with its rendered output โ copy the snippet and swap in your own geometry, functions, or data.
Heart Function ๐ฌ¶
Animate a parametric CalcpadCE plot frame by frame: a #for loop emits one hidden <div> per frame, and a tiny setInterval script cycles through them in the browser.
The same pattern works for any time- or parameter-dependent function.
'<!--'n = 100','PlotWidth = 400','PlotHeight = 350','k = 4','PlotSVG = 1','PlotAdaptive = 0'-->
f(x) = root(x; 3)^2 + 1.1*sin(k*x)*sqrt(4 - x^2)
#val
#rad
#for i = 1 : n
'<div class="frame" id="frame-'i'">
$Plot{f(x) @ x = -2 : 2}
'</div><!--'k = k + 2'-->
#loop
'<script>var i = 1;setInterval(function(){++i; if(i>'n') i=1; $(".frame").hide(); $("#frame-"+i).show();}, 100);</script>
fโ(โxโ)โ =  3  โ x2 + 1.1โยทโsinโ(โkโยทโxโ)โโยทโ   โ 4 โ x2
Plot with Title, Legend and Labels¶
A reference for styling the native 2D plots in CalcpadCE: configure a chart title, axis labels, legend entries and series colours through the PlotTitle, PlotLabelX, PlotLabelY and per-series Plot... options.
Use this as the starting template for any publication-quality plot.
'Functions
f_1(x) = 1'; 'f_2(x) = -1'; 'f_3(x) = x
f_4(x) = 2 - 2*x'; 'f_5(x) = 2 - x'; 'f_6(x) = 2*x - 2
'Points
x_7 = 1', 'y_7 = 0.5'; 'x_8 = 1', 'y_8 = 1.5';
x_9 = 1', 'y_9 = -0.5'; 'x_10 = 1', 'y_10 = -1.5';
'Interval:'a = 0','b = 2
#def title$ = Plot Title
#def series$ = f_1(x) & f_2(x) & x|f_3(x) & x|f_4(x) & x|f_5(x) & x|f_6(x) & x_7|y_7 & x_8|y_8 & x_9|y_9 & x_10|y_10
#def labelX$ = Label X
#def labelY$ = Label Y
#def chart1$ = Line 1
#def chart2$ = Line 2
#def chart3$ = Line 3
#def chart4$ = Line 4
#def chart5$ = Line 5
#def chart6$ = Line 6
#def chart7$ = Point 7
#def chart8$ = Point 8
#def chart9$ = Point 9
#def chart10$ = Point 10
'<div style="width:360pt;">
#hide
PlotWidth = 400','PlotHeight = 200','PlotSVG = 1
#show
'<p><small style="float:left; position:relative; top:10pt;">labelY$</small><center><strong>title$</strong></center>
$Plot{series$ @ x = a : b}
'<small style="float:right;position:relative; top:-10pt;">labelX$</small>
'<b>Legend:</b>
'<p><b style="color:Tomato">โโโ</b> chart1$  
'<b style="color:YellowGreen">โโโ</b> chart2$  
'<b style="color:CornflowerBlue">โโโ</b> chart3$  
'<b style="color:Gold">โโโ</b> chart4$  
'<b style="color:MediumVioletRed">โโโ</b> chart5$  
'<b style="color:MediumSpringGreen">โโโ</b> chart6$
'<br/> <b style="color:BlueViolet">โ</b> chart7$   
'<b style="color:LightSalmon">โ</b> chart8$   
'<b style="color:DeepPink">โ</b> chart9$   
'<b style="color:DarkTurquoise">โ</b> chart10$</p>
'</div>
Functions
f1โ(โxโ)โ = 1 ; f2โ(โxโ)โ = -1 ; f3โ(โxโ)โ = x
f4โ(โxโ)โ = 2 โ 2โยทโx ; f5โ(โxโ)โ = 2 โ x ; f6โ(โxโ)โ = 2โยทโx โ 2
Points
x7 = 1 , y7 = 0.5 ; x8 = 1 , y8 = 1.5 ;
x9 = 1 , y9 = -0.5 ; x10 = 1 , y10 = -1.5 ;
Interval: a = 0 , b = 2
Label Y
โโโ Line 1
โโโ Line 2
โโโ Line 3
โโโ Line 4
โโโ Line 5
โโโ Line 6
โ Point 7
โ Point 8
โ Point 9
โ Point 10
Bolt 3D Model¶
Embed a glTF 3D model directly in a CalcpadCE worksheet using the Google <model-viewer> web component.
Combine the rotating CAD preview with parametric bolt resistance calculations to produce richly illustrated structural connection reports.
Copy the code into the Desktop application to change the parameters in real-time.
'<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.0.1/model-viewer.min.js"></script>
'<model-viewer style="height:280pt;" class="side" src="./Models/bolt_and_nut.glb" alt="bolt_and_nut.glb" auto-rotate camera-controls shadow-intensity="0.5" field-of-view="8deg"></model-viewer>
'<h4>Loads (for one bolt)</h4>
'Tension -'F_t_Ed = ? {20}'kN
'Shear -'F_v_Ed = ? {10}'kN
'<h4>Bolt data</h4>
'<p id="bolt" style="display:none;">'d = ? {12}'</p>
#pre
'<p>Bolt diameter - <select data-target="bolt">
'<option value="12">M12</option>
'<option value="14">M14</option>
'<option value="16">M16</option>
'<option value="18">M18</option>
'<option value="20">M20</option>
'<option value="22">M22</option>
'<option value="24">M24</option>
'<option value="27">M27</option>
'<option value="30">M30</option>
'<option value="36">M36</option>
'</select></p>
#hide
#if d โก 12
A_s = 84' 'd_0 = 13' 'd_m = 20.5
#else if d โก 14
A_s = 115' 'd_0 = 15' 'd_m = 23.5
#else if d โก 16
A_s = 157' 'd_0 = 18' 'd_m = 26
#else if d โก 18
A_s = 192' 'd_0 = 20' 'd_m = 29
#else if d โก 20
A_s = 245' 'd_0 = 22' 'd_m = 32
#else if d โก 22
A_s = 303' 'd_0 = 24' 'd_m = 35.5
#else if d โก 24
A_s = 353' 'd_0 = 26' 'd_m = 39
#else if d โก 27
A_s = 459' 'd_0 = 30' 'd_m = 44
#else if d โก 30
A_s = 561' 'd_0 = 33' 'd_m = 50
#else if d โก 36
A_s = 817' 'd_0 = 39' 'd_m = 60
#end if
#post
'Bolt diameter -'d'mm
'Hole diameter -'d_0'mm
'Punching diameter-'d_m'mm
'Area of the unthreaded part (gross) -'A = ฯ*d^2/4'mmยฒ
'Area of the threaded part (net) -'A_s'mmยฒ
#show
'<p id="grade" style="display:none;">'Grade = ? {10.9}'</p>
#pre
'<p>Bolt steel grade - <select data-target="grade">
'<option value="4.6">4.6</option>
'<option value="4.8">4.8</option>
'<option value="5.6">5.6</option>
'<option value="5.8">5.8</option>
'<option value="6.8">6.8</option>
'<option value="8.8">8.8</option>
'<option value="10.9">10.9</option>
'</select></p>
#hide
f_ub = floor(Grade)
f_yb = (Grade - f_ub)*f_ub*100
f_ub = f_ub*100
#post
#val
'Bolt steel grade - 'Grade
#equ
'Bolt tensile strength -'f_ub'MPa
'Bolt yield strength -'f_yb'MPa
#show
'<h4>Plate data</h4>
'Plate thickness - 't = ? {18}'mm
'Steel yield strength - 'f_y = ? {355}'MPa
#hide
#if f_y โก 235
f_u = 360
#else if f_y โก 275
f_u = 430
#else if f_y โก 355
f_u = 510
#else if f_y โก 420
f_u = 520
#else if f_y โก 460
f_u = 540
#end if
#show
'Steel tensile strength - 'f_u'MPa
'Partial safety factors
ฮณ_M0 = 1.05', 'ฮณ_M2 = 1.25
Tension - Ft_Ed = 20โ kN
Shear - Fv_Ed = 10โ kN
Bolt diameter - d = 12 mm
Hole diameter - d0 = 13 mm
Punching diameter- dm = 20.5 mm
Area of the unthreaded part (gross) - A = ฯโยทโd24 = 3.14โยทโ1224 = 113.1 mmยฒ
Area of the threaded part (net) - As = 84 mmยฒ
Bolt steel grade - 10.9Bolt tensile strength - fub = 1000 MPa
Bolt yield strength - fyb = 900 MPa
Plate thickness - t = 18โ mm
Steel yield strength - fy = 355โ MPa
Steel tensile strength - fu = 510 MPa
Partial safety factors
ฮณM0 = 1.05 , ฮณM2 = 1.25
3D Plot with Plotly¶
Render an interactive 3D surface plot in CalcpadCE by computing a height matrix and embedding it in a Plotly.js chart via inline <script>.
Use this when you need pan, zoom, hover read-outs, or surface shading beyond the built-in plot options.
#hide
#rad
n = 100
A = matrix(n; n)
$Repeat{$Repeat{A.(i; j) = cos(ฯ*(2*i/n - 1))^2 - sin(ฯ*(3*j/n - 1)) + i/n + j/n @ j = 1 : n} @ i = 1 : n}
PlotWidth = 400','PlotHeight = 400
$Map{spline(i; j; A) @ i = 1 : n - 1 & j = 1 : n - 1}
#show
#val
'<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
'<script src="https://cdn.plot.ly/plotly-2.26.0.min.js" charset="utf-8"></script>
'<div id="plotly-chart"></div>
'<script>
'var z_data='A';
'var data = [{
' z: z_data,
' type: "surface",
' colorscale: "YlGnBu",
' contours: {
' z: {
' show:true,
' usecolormap:true,
' highlightcolor:"red",
' project:{z: true}
' }
' }
'}];
'
'var layout = {
' title: {
' text: "Plotly"
' },
' scene: {camera: {eye: {x: 1.5, y: -1.5, z: 1.0}}, aspectmode: "manual", aspectratio: { x: 1, y: 1, z: 0.5}},
' width: 600,
' height: 600,
' margin: {
' l: 50,
' r: 50,
' b: 50,
' t: 50,
' }
'};
'Plotly.newPlot("plotly-chart", data, layout);
'</script>
Parametric 3D Drawing of RC Beam¶
Build a fully parametric 3D model of a reinforced-concrete T-beam (concrete prism plus longitudinal rebars) using three.js inside CalcpadCE. Change the geometry inputs and the WebGL view, the calculations, and the report all update together.
'Beam length -'l = 6m
'Web width -'b = 0.25m', height -'h = 0.8m
'Flange width -'b_f = 1.0m', height -'h_f = 0.14m
'Rebar diameter -'ร = 22mm|m', Concrete cover -'a = 5cm
#val
'<script src="https://cdn.jsdelivr.net/npm/three@0.145/build/three.min.js"></script>
'<script src="https://cdn.jsdelivr.net/npm/three@0.145/examples/js/controls/OrbitControls.js"></script>
'<div id="beam-3d-canvas"></div>
'<script>
'(function() {
'if (typeof THREE === "undefined"|| typeof THREE.OrbitControls === "undefined") {
'alert("Failed to load Three.js or OrbitControls.");
'return;
'}
'const l = 'l'; const a = 'a/m';
'const b = 'b'; const h = 'h';
'const bf = 'b_f'; const hf = 'h_f';
'const scene = new THREE.Scene();
'scene.background = new THREE.Color(0xffffff);
'const camera = new THREE.PerspectiveCamera(50, 2, 0.1*l, 2*l);
'camera.position.set(1.2*bf, 1.3*h, 0.7*l);
'camera.lookAt(0, 0, 0);
'const renderer = new THREE.WebGLRenderer({antialias: true});
'renderer.setSize(600, 350);
'document.getElementById("beam-3d-canvas").appendChild(renderer.domElement);
'const controls = new THREE.OrbitControls(camera, renderer.domElement);
'controls.target.set(0, 0, 0);
'controls.update();
'const light = new THREE.DirectionalLight(0xffffff, 1);
'light.position.set(-4, 8, 10);
'scene.add(light);
'scene.add(new THREE.AmbientLight(0xffffff));
'const shape = new THREE.Shape();
'shape.moveTo(-bf/2, 0);
'shape.lineTo(bf/2, 0);
'shape.lineTo(bf/2, -hf);
'shape.lineTo(b/2, -hf);
'shape.lineTo(b/2, -h);
'shape.lineTo(-b/2, -h);
'shape.lineTo(-b/2, -hf);
'shape.lineTo(-bf/2, -hf);
'shape.lineTo(-bf/2, 0);
'const extrude = new THREE.ExtrudeGeometry(shape, { depth: l, bevelEnabled: false });
'extrude.translate(0, h, -l/2);
'const textureLoader = new THREE.TextureLoader();
'const concreteTexture = textureLoader.load("https://cdn.polyhaven.com/asset_img/primary/concrete_layers_02.png?height=760&quality=95");
'concreteTexture.wrapS = THREE.RepeatWrapping;
'concreteTexture.wrapT = THREE.RepeatWrapping;
'concreteTexture.repeat.set(b, 0.5*b);
'const concreteMaterial = new THREE.MeshStandardMaterial({
'map: concreteTexture, roughness: 1, metalness: 0.1, transparent: true, opacity:0.9});
'const beam = new THREE.Mesh(extrude, concreteMaterial);
'scene.add(beam);
'const r = 'ร/2';
'const geometry = new THREE.CylinderGeometry(r, r, 1.04*l, 32);
'geometry.rotateX(Math.PI / 2);
'const steelMaterial = new THREE.MeshStandardMaterial({
'color: 0xff0000,
'metalness: 0.8,
'roughness: 0.4
'});
'const xb1 = b/2 - a;
'const yb1 = a; const yb2 = h - a;
'const xb = [xb1, -xb1, xb1, -xb1];
'const yb = [yb1, yb1, yb2, yb2];
'const zb = 0;
'var rebar = new THREE.Mesh(geometry, steelMaterial);
'for(var i = 0; i < 4; ++i){
'rebar.position.set(xb[i], yb[i], zb);
'scene.add(rebar);
'rebar = rebar.clone();
'}
'function animate() {
'requestAnimationFrame(animate);
'renderer.render(scene, camera);
'}
'animate();
'})();
'</script>
Beam length - l = 6โm
Web width - b = 0.25โm , height - h = 0.8โm
Flange width - bf = 1โm , height - hf = 0.14โm
Rebar diameter - ร = 22โmm = 0.022โm , Concrete cover - a = 5โcm
Plotting Easter Egg in 2D and 3D¶
Render the same egg-shaped curve as a 2D parametric plot and as a shaded 3D surface side by side, illustrating the difference between the $Plot and $Map plot directives in CalcpadCE and the role of PlotShadows, PlotPalette and PlotLightDir.
#md on
a = 1'- horizontal radius
b = 0.7'- vertical radius
#rad
'<!--'PlotWidth = 400', 'PlotHeight = PlotWidth', 'PlotStep = 1', ' _
PlotShadows = 1', 'PlotPalette = 4', 'PlotLightDir = 7'-->
'<table><tr><td>
x(t) = a*cos(t)
y(t) = b*(1 - 0.2*cos(t))*sin(t)
$Plot{x(t)|y(t) & -1|-1 & 1|1 @ t = 0 : 2*ฯ}
'</td><td>
f(x; y) = b*(1 - 0.2*cos(acos(x/a)))*sin(acos(x/a))
z(x; y) = sqrt(f(x; y)^2 - y^2)
$Map{z(x; y) @ x = -1 : 1 & y = -1 : 1}
'</td></tr></table>
a = 1 - horizontal radius
b = 0.7 - vertical radius
|
xโ(โtโ)โ = aโยทโcosโ(โtโ)โ yโ(โtโ)โ = bโยทโโ(โ1 โ 0.2โยทโcosโ(โtโ)โโ)โโยทโsinโ(โtโ)โ |
fโ(โx; yโ)โ = bโยทโ(1 โ 0.2โยทโcos(acos(xa)))โยทโsin(acos(xa)) zโ(โx; yโ)โ =   โ fโโ(โx; yโ)โ2 โ y2 |
Parametric SVG Generation¶
Generate a fully parametric SVG cross-section of a prestressed double-tee panel by composing reusable #def shape templates from svg_drawing.cpd.
Adjust any dimension and the drawing redraws itself โ ideal for standardised structural detail libraries.
#include svg_drawing.cpd
"Prestressed TT Panel - Parametric SVG Generation
#deg
'Dimensions:
'Rib height -'h = ? {750}'mm
'Rib top width -'b_2 = ? {200}'mm
'Slab depth -'h_f = ? {100}'mm
'Rib spacing c/c -'B_0 = ? {1500}'mm
'Slab width -'B = ? {2500}'mm
#post
'Total height -'H = h + h_f'mm
'Rib bottom width -'b_1 = b_2 - (h - 30)/10'mm
'- mean -'b_w = (b_1 + b_2)/2'mm
'- at <var>z</var> from top -'b(z) = b_2 - (b_2 - b_1)*z/h'mm
'Rib effective width -'b_f = B/2'mm
#post
#show
'Distance from the center of the first row of tendons to the bottom edge -'d_p1 = ? {80}'mm
'Number of tendons in one row -'n_ph = ? {2}'
'Number of rows -'n_pv = ? {3}'
#pre
#hide
x_1 = B_0/2
x_2 = x_1 + b_2/2
x_3 = x_2 + 140
x_4 = x_1 + b_1/2
x_5 = x_4 - b_1
x_6 = x_2 - b_2
x_7 = x_6 - 140
x_8 = x_1 - 20*(n_ph - 1)
#post
#val
'<svg viewbox="'-b_f - 200' -150 'B + 300' 'H + 400'" xmlns="http://www.w3.org/2000/svg" version="1.1" style="font-family: Arial Nova Cond, Noto Sans Cond, Segoe UI; font-size: '54'px; width:500pt; height:'500*H/B + 50'pt">
'<polygon points="'b_f','0' 'b_f','h_f' 'x_3','h_f' 'x_2','h_f + 30' 'x_4','H' 'x_5','H' 'x_6','h_f + 30' 'x_7','h_f' '-x_7','h_f' '-x_6','h_f + 30' '-x_5','H' '-x_4','H' '-x_2','h_f + 30' '-x_3','h_f' '-b_f','h_f' '-b_f','0'" sec_style$/>
line$(-x_1; -100; -x_1; H + 100; axis_style$)
line$( x_1; -100; x_1; H + 100; axis_style$)
dimh$(-b_f; b_f; -60; B = 'B' mm)
dimv$(-b_f - 60; 0; H; H = 'H' mm)
dimv$(-b_f + 80; 0; h_f; h<tspan dy=20>f</tspan><tspan dy=-20> = </tspan>'h_f' mm )
dimv$(-b_f + 80; h_f; H; <tspan dy=100>h = 'h' mm</tspan>)
dimh$(-x_1; x_1; H + 180; B<tspan dy=5>โ</tspan><tspan dy=-5> = 'B_0'</tspan> mm)
dimh$(-x_2; -x_6; h_f + 120; b<tspan dy=5>โ</tspan><tspan dy=-5> = </tspan>'b_2' mm)
dimh$(-x_4; -x_5; H + 80; b<tspan dy=5>โ</tspan><tspan dy=-5> = </tspan>'b_1' mm)
#hide
#def tendon$ = r="10" style="stroke:red; fill:red; stroke-width:1"
i = 0
#repeat n_pv
j = 0
#repeat n_ph
#post
'<circle cx="'x_8 + 40*j'" cy="'H - d_p1 - 40*i'" tendon$/>
'<circle cx="'-x_8 - 40*j'" cy="'H - d_p1 - 40*i'" tendon$/>
#hide
j = j + 1
#loop
i = i + 1
#loop
#post
'</svg>
#equ
Dimensions:
Rib height - h = 750โ mm
Rib top width - b2 = 200โ mm
Slab depth - hf = 100โ mm
Rib spacing c/c - B0 = 1500โ mm
Slab width - B = 2500โ mm
Total height - H = h + hf = 750 + 100 = 850 mm
Rib bottom width - b1 = b2 โ h โ 3010 = 200 โ 750 โ 3010 = 128 mm
- mean - bw = b1 + b22 = 128 + 2002 = 164 mm
- at z from top - bโ(โzโ)โ = b2 โ โ(โb2 โ b1โ)โโยทโzh mm
Rib effective width - bf = B2 = 25002 = 1250 mm
Distance from the center of the first row of tendons to the bottom edge - dp1 = 80โ mm
Number of tendons in one row - nph = 2โ
Number of rows - npv = 3โ
Spotted an error? Edit these examples.