This JavaScript Reference section displays the code for an example program that shows how to draw a 3d surface plot with lighting using scalable vector graphics (SVG).
<!DOCTYPE html> <html> <head> <title>XoaX.net's Javascript</title> </head> <body> <script type="text/javascript" src="Svg3dGraph.js"></script> </body> </html>
var qBody = document.getElementsByTagName("body")[0]; function CProjectedPoint(dX,dY,dZ) { var dScale = 250.0; var dDuDx = .612; var dDuDy = -dDuDx; var dDuDz = 0.0; var dDvDx = .25; var dDvDy = .25; var dDvDz = -.866; this.mdU = (dDuDx*dX + dDuDy*dY + dDuDz*dZ)*dScale; this.mdV = (dDvDx*dX + dDvDy*dY + dDvDz*dZ)*dScale; } var qMainDiv = document.createElementNS("http://www.w3.org/2000/svg", "svg") qMainDiv.style.backgroundColor = "#eeeecc"; qMainDiv.style.width="800px"; qMainDiv.style.height="800px"; qMainDiv.style.position="absolute"; // Bottom x = [-1, 1], y = [-1, 1], z = -1 // scale var qBottom = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); var cx = 400; var cy = 400; var qP1 = new CProjectedPoint(-1.0, -1.0, -1.0); var qP2 = new CProjectedPoint(-1.0, 1.0, -1.0); var qP3 = new CProjectedPoint(1.0, 1.0, -1.0); var qP4 = new CProjectedPoint(1.0, -1.0, -1.0); var dCoords = (qP1.mdU + cx) + " " + (qP1.mdV + cy) + " " + (qP2.mdU + cx) + " " + (qP2.mdV + cy) + " " + (qP3.mdU + cx) + " " + (qP3.mdV + cy) + " " + (qP4.mdU + cx) + " " + (qP4.mdV + cy); qBottom.setAttribute('points', dCoords); qBottom.setAttribute('fill', '#ffbbbb'); qBottom.setAttribute('fill-rule', 'nonzero'); qMainDiv.appendChild(qBottom); // Left x = -1, y = [-1, 1], z = [-1, 1] // scale var qLeftSide = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); qP1 = new CProjectedPoint(-1.0, 1.0, 1.0); qP2 = new CProjectedPoint(-1.0, 1.0, -1.0); qP3 = new CProjectedPoint(-1.0, -1.0, -1.0); qP4 = new CProjectedPoint(-1.0, -1.0, 1.0); dCoords = (qP1.mdU + cx) + " " + (qP1.mdV + cy) + " " + (qP2.mdU + cx) + " " + (qP2.mdV + cy) + " " + (qP3.mdU + cx) + " " + (qP3.mdV + cy) + " " + (qP4.mdU + cx) + " " + (qP4.mdV + cy); qLeftSide.setAttribute('points', dCoords); qLeftSide.setAttribute('fill', '#ffeeee'); qLeftSide.setAttribute('fill-rule', 'nonzero'); qMainDiv.appendChild(qLeftSide); // Right x = [-1, 1], y = -1, z = [-1, 1] // scale var qRightSide = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); qP1 = new CProjectedPoint(1.0, -1.0, 1.0); qP2 = new CProjectedPoint(1.0, -1.0, -1.0); qP3 = new CProjectedPoint(-1.0, -1.0, -1.0); qP4 = new CProjectedPoint(-1.0, -1.0, 1.0); dCoords = (qP1.mdU + cx) + " " + (qP1.mdV + cy) + " " + (qP2.mdU + cx) + " " + (qP2.mdV + cy) + " " + (qP3.mdU + cx) + " " + (qP3.mdV + cy) + " " + (qP4.mdU + cx) + " " + (qP4.mdV + cy); qRightSide.setAttribute('points', dCoords); qRightSide.setAttribute('fill', '#ffd8d8'); qRightSide.setAttribute('fill-rule', 'nonzero'); qMainDiv.appendChild(qRightSide); // Border - hexagon around the graph // scale var qBorder = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); qP1 = new CProjectedPoint(-1.0, -1.0, 1.0); qP2 = new CProjectedPoint(1.0, -1.0, 1.0); qP3 = new CProjectedPoint(1.0, -1.0, -1.0); qP4 = new CProjectedPoint(1.0, 1.0, -1.0); var qP5 = new CProjectedPoint(-1.0, 1.0, -1.0); var qP6 = new CProjectedPoint(-1.0, 1.0, 1.0); dCoords = (qP1.mdU + cx) + " " + (qP1.mdV + cy) + " " + (qP2.mdU + cx) + " " + (qP2.mdV + cy) + " " + (qP3.mdU + cx) + " " + (qP3.mdV + cy) + " " + (qP4.mdU + cx) + " " + (qP4.mdV + cy) + " " + (qP5.mdU + cx) + " " + (qP5.mdV + cy) + " " + (qP6.mdU + cx) + " " + (qP6.mdV + cy); qBorder.setAttribute('points', dCoords); qBorder.setAttribute('fill', '#ffeedd'); qBorder.setAttribute('fill-rule', 'nonzero'); qBorder.setAttribute('stroke-width', '4'); qBorder.setAttribute('stroke', 'rgb(255, 128, 128)'); qMainDiv.appendChild(qBorder); // Inner (background) Lines var qLineZ = document.createElementNS("http://www.w3.org/2000/svg", "line"); qP1 = new CProjectedPoint(-1.0, -1.0, 1.0); qP2 = new CProjectedPoint(-1.0, -1.0, -1.0); qLineZ.setAttribute('x1', qP1.mdU + cx); qLineZ.setAttribute('y1', qP1.mdV + cy); qLineZ.setAttribute('x2', qP2.mdU + cx); qLineZ.setAttribute('y2', qP2.mdV + cy); qLineZ.setAttribute('stroke-width', '2'); qLineZ.setAttribute('stroke', 'rgb(255, 128, 128)'); qMainDiv.appendChild(qLineZ); var qLineY = document.createElementNS("http://www.w3.org/2000/svg", "line"); qP1 = new CProjectedPoint(-1.0, 1.0, -1.0); qP2 = new CProjectedPoint(-1.0, -1.0, -1.0); qLineY.setAttribute('x1', qP1.mdU + cx); qLineY.setAttribute('y1', qP1.mdV + cy); qLineY.setAttribute('x2', qP2.mdU + cx); qLineY.setAttribute('y2', qP2.mdV + cy); qLineY.setAttribute('stroke-width', '2'); qLineY.setAttribute('stroke', 'rgb(255, 128, 128)'); qMainDiv.appendChild(qLineY); var qLineX = document.createElementNS("http://www.w3.org/2000/svg", "line"); qP1 = new CProjectedPoint(1.0, -1.0, -1.0); qP2 = new CProjectedPoint(-1.0, -1.0, -1.0); qLineX.setAttribute('x1', qP1.mdU + cx); qLineX.setAttribute('y1', qP1.mdV + cy); qLineX.setAttribute('x2', qP2.mdU + cx); qLineX.setAttribute('y2', qP2.mdV + cy); qLineX.setAttribute('stroke-width', '2'); qLineX.setAttribute('stroke', 'rgb(255, 128, 128)'); qMainDiv.appendChild(qLineX); var dDeltaX = 2.0/100.0; var dDeltaY = 2.0/100.0; var daaZ = new Array(101); // Calculate the z values for (var x = 0; x < 101; ++x) { daaZ[x] = new Array(101); for (var y = 0; y < 101; ++y) { var dX = -1 + x*dDeltaX; var dY = -1 + y*dDeltaY; var dZ = (dX*dX + dY*dY)*10; if (dZ < 1.0e-5) { daaZ[x][y] = 1.0; } else { daaZ[x][y] = (Math.sin(3*dZ)/(3*dZ)); } } } function Normalize(daV) { var dLength = Math.sqrt(daV[0]*daV[0] + daV[1]*daV[1] + daV[2]*daV[2]); daV[0] /= dLength; daV[1] /= dLength; daV[2] /= dLength; } function Cross(daV1, daV2) { var daN = new Array(3); daN[0] = daV1[1]*daV2[2] - daV1[2]*daV2[1]; daN[1] = daV1[2]*daV2[0] - daV1[0]*daV2[2]; daN[2] = daV1[0]*daV2[1] - daV1[1]*daV2[0]; return daN; } // Compute the light reflectance on the triangle from above - take the z value function Light(daaT) { var daaV = new Array(2); daaV[0] = new Array(3); daaV[1] = new Array(3); for (var k = 0; k < 3; ++k) { daaV[0][k] = daaT[1][k] - daaT[0][k]; daaV[1][k] = daaT[2][k] - daaT[0][k]; } // Normalize those vectors, which are the sides of the triangle Normalize(daaV[0]); Normalize(daaV[1]); // Take a Cross Product to get the normal vector var daN = Cross(daaV[0], daaV[1]); Normalize(daN); return Math.abs(daN[2]); } var qGroup = document.createElementNS("http://www.w3.org/2000/svg", "g"); var daaTriangle = new Array(3); daaTriangle[0] = new Array(3); daaTriangle[1] = new Array(3); daaTriangle[2] = new Array(3); var daaProjTri = new Array(3); for (var i = 0; i < 100; ++i) { for (var j = 0; j < 100; ++j) { // Triangle 1 daaTriangle[0][0] = -1 + i*dDeltaX; daaTriangle[0][1] = -1 + j*dDeltaY; daaTriangle[0][2] = daaZ[i][j]; daaTriangle[1][0] = -1 + (i+1)*dDeltaX; daaTriangle[1][1] = -1 + j*dDeltaY; daaTriangle[1][2] = daaZ[i+1][j]; daaTriangle[2][0] = -1 + i*dDeltaX; daaTriangle[2][1] = -1 + (j+1)*dDeltaY; daaTriangle[2][2] = daaZ[i][j+1]; var qTriangle = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); daaProjTri[0] = new CProjectedPoint(daaTriangle[0][0], daaTriangle[0][1], daaZ[i][j]); daaProjTri[1] = new CProjectedPoint(daaTriangle[1][0], daaTriangle[1][1], daaZ[i+1][j]); daaProjTri[2] = new CProjectedPoint(daaTriangle[2][0], daaTriangle[2][1], daaZ[i][j+1]); dCoords = (daaProjTri[0].mdU + cx) + " " + (daaProjTri[0].mdV + cy) + " " + (daaProjTri[1].mdU + cx) + " " + (daaProjTri[1].mdV + cy) + " " + (daaProjTri[2].mdU + cx) + " " + (daaProjTri[2].mdV + cy); qTriangle.setAttribute('points', dCoords); var dLight = Light(daaTriangle); var qColor = 'rgb(' + Math.floor(dLight*128 + 100) + ', ' + Math.floor(dLight*128 + 127.9) + ', ' + Math.floor(dLight*128 + 100) + ')'; qTriangle.setAttribute('fill', qColor); qTriangle.setAttribute('fill-rule', 'nonzero'); qTriangle.setAttribute('stroke-width', '1'); qTriangle.setAttribute('stroke', qColor); qGroup.appendChild(qTriangle); // Triangle 2 daaTriangle[0][0] = -1 + (i+1)*dDeltaX; daaTriangle[0][1] = -1 + (j+1)*dDeltaY; daaTriangle[0][2] = daaZ[i+1][j+1]; qTriangle = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); daaProjTri[0] = new CProjectedPoint(daaTriangle[0][0], daaTriangle[0][1], daaZ[i+1][j+1]); dCoords = (daaProjTri[0].mdU + cx) + " " + (daaProjTri[0].mdV + cy) + " " + (daaProjTri[1].mdU + cx) + " " + (daaProjTri[1].mdV + cy) + " " + (daaProjTri[2].mdU + cx) + " " + (daaProjTri[2].mdV + cy); qTriangle.setAttribute('points', dCoords); dLight = Light(daaTriangle); qColor = 'rgb(' + Math.floor(dLight*128 + 100) + ', ' + Math.floor(dLight*128 + 127.9) + ', ' + Math.floor(dLight*128 + 100) + ')'; qTriangle.setAttribute('fill', qColor); qTriangle.setAttribute('fill-rule', 'nonzero'); qTriangle.setAttribute('stroke-width', '1'); qTriangle.setAttribute('stroke', qColor); qGroup.appendChild(qTriangle); } } qMainDiv.appendChild(qGroup); // Outer Lines qLineZ = document.createElementNS("http://www.w3.org/2000/svg", "line"); qP1 = new CProjectedPoint(1.0, 1.0, 1.0); qP2 = new CProjectedPoint(1.0, 1.0, -1.0); qLineZ.setAttribute('x1', qP1.mdU + cx); qLineZ.setAttribute('y1', qP1.mdV + cy); qLineZ.setAttribute('x2', qP2.mdU + cx); qLineZ.setAttribute('y2', qP2.mdV + cy); qLineZ.setAttribute('stroke-width', '1'); qLineZ.setAttribute('stroke', 'rgb(255, 128, 128)'); qMainDiv.appendChild(qLineZ); qLineY = document.createElementNS("http://www.w3.org/2000/svg", "line"); qP1 = new CProjectedPoint(1.0, 1.0, 1.0); qP2 = new CProjectedPoint(1.0, -1.0, 1.0); qLineY.setAttribute('x1', qP1.mdU + cx); qLineY.setAttribute('y1', qP1.mdV + cy); qLineY.setAttribute('x2', qP2.mdU + cx); qLineY.setAttribute('y2', qP2.mdV + cy); qLineY.setAttribute('stroke-width', '1'); qLineY.setAttribute('stroke', 'rgb(255, 128, 128)'); qMainDiv.appendChild(qLineY); qLineX = document.createElementNS("http://www.w3.org/2000/svg", "line"); qP1 = new CProjectedPoint(1.0, 1.0, 1.0); qP2 = new CProjectedPoint(-1.0, 1.0, 1.0); qLineX.setAttribute('x1', qP1.mdU + cx); qLineX.setAttribute('y1', qP1.mdV + cy); qLineX.setAttribute('x2', qP2.mdU + cx); qLineX.setAttribute('y2', qP2.mdV + cy); qLineX.setAttribute('stroke-width', '1'); qLineX.setAttribute('stroke', 'rgb(255, 128, 128)'); qMainDiv.appendChild(qLineX); qBody.appendChild(qMainDiv);
© 20072024 XoaX.net LLC. All rights reserved.