Skip to content

Instantly share code, notes, and snippets.

@chriswmackey
Last active April 25, 2018 22:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriswmackey/19369713e0b853314b79426b4d21b3ba to your computer and use it in GitHub Desktop.
Save chriswmackey/19369713e0b853314b79426b4d21b3ba to your computer and use it in GitHub Desktop.
Axonometric Grid
license: mit
{"root":[
{"row": [1,1,1,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [0,0,0,1,0,0,0,0,0,0]},
{"row": [0,0,0,0,0,0,0,0,1,0]},
{"row": [1,0,0,1,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [1,1,0,0,0,0,0,0,0,0]},
{"row": [0,0,0,0,0,0,0,0,0,0]},
{"row": [0,0,0,1,0,0,0,0,0,0]},
{"row": [1,0,0,0,0,0,0,1,1,1]},
{"row": [0,1,1,0,0,0,0,0,0,1]}
]
}
<!DOCTYPE html>
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<style>
#inputSliders { font-family:sans-serif;outline:none;padding-top:15px;width:960px;margin: 0 auto;}
#content { width:960px;margin: 0 auto;}
.inputgroup {border:none;}
.slider { width:210px;float:left;padding:10px;}
label { float:left;font-weight:bold;padding-bottom:10px;}
input[type=range] { float:left;clear:left;margin-right:10px;width:130px;}
input[type=range]::-ms-track { background: transparent;border-color: transparent;color: transparent;-webkit-appearance: none}
input[type=range]::-ms-track { -ms-appearance: none; height: 3px;background-color: #d5d5d5; margin-right: 0;
margin-top: 5px;margin-bottom: 5px; border:0; }
input[type=range]::-ms-thumb { background-color: #FFF; border: 3px solid rgb(150,150,150);
border-radius: 5px; height: 10px;width: 1px; }
input[type=range]::-webkit-slider-runnable-track { height: 5px;background:#7c7c7c; margin-top: -4px;}
input[type=range]::-webkit-slider-thumb { margin-top:-6px;}
#inputSliders p {padding-top:10px;}
</style>
</head>
<body>
<div id="inputSliders">
<form id="sliders" autocomplete="off">
<fieldset class="inputgroup">
<div class="slider" id="angle_X">
<label>Angle X axis(deg)</label>
<input type="range" name="angleX" id="angleX" value="25" min="0" max="80" step = "1"><p id="angXoutput">25°</p></div>
<div class="slider" id="angle_Y">
<label>Angle Y axis</label>
<input type="range" name="angleY" id="angleY" value="25" min="0" max="80" step = "1"><p id="angYoutput">25°</p></div>
<div class="slider" id="grid_elev">
<label>Grid elevation</label>
<input type="range" name="elev" id="elev" value="0" min="0" max="50" step = "1"><p id="elevoutput">0ft</p></div>
<div class="slider" id="grid_Size">
<label>Grid Size</label>
<input type="range" name="gridSize" id="gridSize" value="360" min="200" max="380" step = "1"><p id="gridSizeoutput">360</p></div>
</fieldset>
</form>
</div>
<script>
// Get inputs from the sliders
var isoAngleX = $("#angleX").val().toString(); // Air tmperature in Celcius
var isoAngleY = $("#angleY").val().toString(); // Mean radiant tmperature in Celcius
var gridElevation = $("#elev").val().toString(); // Wind velocity in m/s
var gridSize = $("#gridSize").val().toString(); // Relative humidity in %
// Update inputs
$("#angleX").on("input", function(event) {
isoAngleX = $(this).val();
$("#angXoutput").text(isoAngleX.toString() + "°");
generateIsoGeometry("update");
});
$("#angleY").on("input", function(event) {
isoAngleY = $(this).val();
$("#angYoutput").text(isoAngleY.toString() + "°");
generateIsoGeometry("update");
});
$("#elev").on("input", function(event) {
gridElevation = $(this).val();
$("#elevoutput").text(gridElevation.toString() + "ft");
generateIsoGeometry("update");
});
$("#gridSize").on("input", function(event) {
gridSize = $(this).val();
$("#gridSizeoutput").text(gridSize.toString());
generateIsoGeometry("update");
});
//grid settings
var gridSizeX = gridSize; //overal grid dimensions in svg units
var gridSizeY = gridSize;
var cols = 20;
var rows = 20;
//var gridElevation = 0
//var isoAngleX = 35;
//var isoAngleY = 35;
var zCoeficient = gridSize/360;
//grid format settings
var fillColorOn = "#f94200";
var fillColorOff = "#cce9fe";
var fillOpacity = 1
var strokeColor = "white";
var strokeWidth = 1;
var strokeOpacity = 1;
//facade format settings
var wallFormat = {}
wallFormat.strokeColor = "black";
wallFormat.strokeOpacity = .5;
wallFormat.strokeWidth = 2
wallFormat.fillColor = "white";
wallFormat.fillOpacity = .3;
//window format settings
var windowFormat = {}
windowFormat.strokeColor = "black";
windowFormat.strokeOpacity = .5;
windowFormat.strokeWidth = 1
windowFormat.fillColor = "#84e4ff";
windowFormat.fillOpacity = .3;
var canvas = d3.select("body").append("svg")
.attr("width", 800)
.attr("height", 600)
.append("g")
.attr("transform", "translate(50, 250)");
generateIsoGeometry("new");
function generateIsoGeometry(mode) {
gridSizeX = gridSize; //overal grid dimensions in svg units
gridSizeY = gridSize;
zCoeficient = gridSize/360;
//Facade Section
// temp. facade data from Chris
var wallSizeZ = 100;//overal grid dimensions in svg units
var r = {};
r.wallCoords = [{x:0, y:0, z:0}, {x:gridSizeX, y:0, z:0},
{x:gridSizeX, y:0, z:wallSizeZ*zCoeficient}, {x:0, y:0, z:wallSizeZ*zCoeficient}];
r.glzCoords = [
[{x:gridSizeX*.05, y:0, z:0}, {x:gridSizeX*.3, y:0, z:0},{x:gridSizeX*.3, y:0, z:80*zCoeficient}, {x:gridSizeX*.05, y:0, z:80*zCoeficient}],
[{x:gridSizeX*.35, y:0, z:0}, {x:gridSizeX*.6, y:0, z:0},{x:gridSizeX*.6, y:0, z:80*zCoeficient}, {x:gridSizeX*.35, y:0,z:80*zCoeficient}],
[{x:gridSizeX*.65, y:0, z:0}, {x:gridSizeX*.9, y:0, z:0},{x:gridSizeX*.9, y:0, z:80*zCoeficient}, {x:gridSizeX*.65, y:0, z:80*zCoeficient}]
];
// Prepare wall and windows data
var facadeData = [prepShape(r.wallCoords, wallFormat)];
for (i=0;i < r.glzCoords.length; i++) {
facadeData.push(prepShape(r.glzCoords[i], windowFormat));
}
//Grid Section
d3.json("gridData.json", function (data) {
//create temp array of tile values from json file
//(will replace with Chris data)
var tileVals = [];
data.root.forEach(function(entry) {
for (i=0; i < entry.row.length; i++) {
tileVals.push({val:entry.row[i]})
}
});
//create array of tile origin pts and fill values
var tileSizeX = gridSizeX/cols;
var tileSizeY = gridSizeY/rows;
var originTiles = [];
for (iRow=0; iRow < rows; iRow++){
for (iCol=0; iCol < cols; iCol++){
var valIndex = iRow*rows+iCol;
var val = valIndex < tileVals.length ? tileVals[valIndex].val: 0;
var originX = tileSizeX*iCol;
var originY = tileSizeY*iRow;
originTiles.push({val:val, x:originX, y:originY})
}
}
//convert orthogonal orign grid points to isometric points
originTiles.forEach(function(entry) {
z = -gridElevation * zCoeficient;
res = isoPoint(entry.x, entry.y, z, isoAngleX, isoAngleY);
entry.x = res[0];
entry.y = res[1];
});
//base tile shape point loop
var tilePts = [{x:originTiles[0].x, y:originTiles[0].y},
{x:originTiles[1].x, y:originTiles[1].y},
{x:originTiles[cols+1].x, y:originTiles[cols+1].y},
{x:originTiles[cols].x, y:originTiles[cols].y},
{x:originTiles[0].x, y:originTiles[0].y}
];
//create final list of tiles with five shape points each
//by adding the base pts to each tile's origin
var isoTilesPts = [];
for (i=0; i< originTiles.length; i++){
tmpShapePts = [];
for (p=0; p < tilePts.length; p++){
newPt = JSON.parse(JSON.stringify(tilePts[p]));
newPt.x = newPt.x + originTiles[i].x;
newPt.y = newPt.y + originTiles[i].y;
newPt.fc = originTiles[i].val?fillColorOn:fillColorOff;
newPt.fo = fillOpacity;
newPt.sc = strokeColor;
newPt.sw = strokeWidth;
newPt.so = strokeOpacity;
tmpShapePts.push(newPt);
}
isoTilesPts.push(tmpShapePts);
}
// Consolidate grid and facade data
var shapeData = isoTilesPts;
for (i=0;i < facadeData.length; i++) {
shapeData.push(facadeData[i]);
}
drawShapes(shapeData, mode);
})
}
// Prepare Data to Isometric format
function prepShape(shapePts, shapeFormat){
//convert orthogonal orign points to isometric points
shapePts.forEach(function(entry) {
res = isoPoint(entry.x, entry.y, -entry.z, isoAngleX, isoAngleY);
entry.x = res[0];
entry.y = res[1];
entry.fc = shapeFormat.fillColor;
entry.fo = shapeFormat.fillOpacity;
entry.sc = shapeFormat.strokeColor;
entry.sw = shapeFormat.strokeWidth;
entry.so = shapeFormat.strokeOpacity;
});
shapePts.push(shapePts[0]); // add first point to compelte loop
return shapePts;
}
// Draw shapes
function drawShapes(shapePtLoops, mode) {
//line function for path shape
var line = d3.line()
.x(function(d){return d.x;})
.y(function(d){return d.y;});
//create shapes through path objects
paths = null;
if (mode=='new') {
paths = canvas.selectAll("path")
.data(shapePtLoops)
.enter().append("path");
} else {
paths = canvas.selectAll("path")
.data(shapePtLoops)
}
paths.attr("d", line)
.attr("stroke", function(d){return d[0].sc} )
.attr("stroke-width", function(d, i){return d[0].sw})
.attr("stroke-opacity", function(d){return d[0].so})
.attr("fill", function(d){return d[0].fc})
.attr("fill-opacity", function(d){return d[0].fo});
}
//Obtain isometric points from 2d points based on predefined angles
function isoPoint(x,y,z, isoAngleX, isoAngleY) {
var radX = (isoAngleX)*Math.PI/180;
var radY = (isoAngleY)*Math.PI/180;
var u0X = adjacentCos(radX, x);
var u0Y = oppositeSin(radX, x);
var v0X = adjacentCos(radY, y);
var v0Y = oppositeSin(radY, y);
//var locX = u0X-v0X;
//var locY = u0Y+v0Y;
var locX = u0X+v0X;
var locY = -u0Y+v0Y+z;
return [locX, locY];
}
// Triangle math functions
//returns the length of the adjacent side to the angle, using the hypotenuse's length
function adjacentCos(angle, hypotenuse) {
return Math.cos(angle) * hypotenuse;
}
//returns the length of the opposite side to the angle, using the hypotenuse's length
function oppositeSin(angle, hypotenuse) {
return Math.sin(angle) * hypotenuse;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment