This site uses cookies – More Information.
Henge
Henge is an exploration of circular megalithic structures of the prehistoric age. It is a work of historical fiction where these stone assemblies, achieved through herculean efforts of stacking, aligning, and balancing immense chiseled rocks, are reimagined within an alternate universe of algorithmic possibility.
Henges share a few qualities that inspired this project. They are places of gathering within a loose collection of stones to organize ceremony or worship under celestial alignments. They are also monolithic in their materiality and employ the most elemental techniques of megalithic, or large stone, construction. These particular types of henges, known as cromlechs, are circular spaces fit with purpose and ritual and in this sense, serve as precedents to the great human edifices, charging landscapes with meaning and presence through geometry and order.
Finally, henges are a collective language of place-making shared across a range of cultures and ages, from the Mesolithic and Neolithic eras and across territories from modern-day Portugal, Germany, Scandinavia, to the well-known Stone Henge in Great Britain.
This project is deeply inspired by the timeless and universal narrative created through a thoughtful and deliberate placement of large rocks in a circle. It seems that when confronted with marking a place and communing with nature, human beings like to make circles out of stones. Among all the symbols of place making, the circle is the original and still remains the most universal.
HISTORY IS GENERATIVE
Henge animates the history of these circles, their roughness and seemingly endless variation. Its not a truthful recreation but a re-living the moment through new eyes. The following are some test outputs:
HENGE DESIGN
The following attributes define some of the Henge features:
ATMOSPHERE
For Henge’s atmosphere, its clouds and weather, we were inspired by Piranesi’s spectacular cloud formations in his engravings. These skies are cropped from Vedute di Roma (Views of Rome) by Giovanni Battista Piranesi, ca. 1750–78.
HENGE AS ARCHITECTURAL SPECULATION
Proportion and geometry are at work in this henge analysis by architect Inigo Jones. At the request of the king, Jones tried to prove that Stone Henge was actually the ruins of a Roman temple through a geometrical forensics. Despite being completely wrong, he produced the first thorough monographic analysis of a building in the United Kingdom, evidence that a re-imagining of a henge need not be factually correct to inspire architectural speculation.
HENGE LAYOUTS
Each Henge has a randomized size, density, and category, or multiple categories overlaid to determine it’s layout. The categories are:
- Ring: a circle of stones equidistant from the center.
- Disk: stones randomly placed anywhere in a disk.
- Random: stones randomly placed anywhere in a circle.
- Bi-Axial Symmetry: stones arranged symmetrically across two axes.
- Radial Symmetry: stone positions mirrored across multiple axes.
- Vertical Symmetry: stone positions mirrored across one axis.
HENGE STACKS
Stone stack variations. The category determines the length, width, height, and amount of stones.
- Regular: other categories are based off this one.
- Short: Larger length and width. Smaller height and amount.
- Large: Larger length, width, and height. Smaller amount.
- Long: Larger length, smaller width.
- Thin: Larger amount. Smaller length,width, and height.
- Tall: larger amount. smaller width and height.
Every Henge is a three dimensional landscape viewable in four drawing conventions: plan, perspective, elevation, and isometric.
400 Henges minted outputs in PixPlot, a convolutional neural network and Uniform Manifold Approximation and Projection (UMAP) in order to cluster visually similar images near one another.
ANOTHER CIRCLE
Henge extends our fascination with stone landscapes. Our project Another Circle used salvaged limestone to create a temporary public space for Mill Race Park in Columbus, Indiana.
Read our essay about History is Generative to learn more.
Plot generation code
////////////////// Aranda\lasch
////////////////// Jesse Bassett
////////////////// 5/20/2022 v3.3
function roll() {
plot = makePlot(0);
}
class Plotattributes{
constructor(_category,_size,_density,_stackAmount) {
this.category = _category,//type of generation
this.size = _size,//size/scale
this.density = _density,//density of stacks
this.amount = _stackAmount,//number of stacks
this.x = [],//List of X for stacks
this.y = []//List of Y for stacks
}
}
function makePlot(_arg,_argCat,_argSize,_argAmount){
let _plotCat = shuffle(plotCategories)[0];
let _plotSize = floor(random(1000,2000));//circle radius
let _plotDen = random(.02,.05); //density with respect to radius not area.
let _plotAmount = floor(_plotSize*_plotDen);
let _plot;
if (_arg === 0){
_plot = new Plotattributes(_plotCat,_plotSize,_plotDen,_plotAmount);
}
else if (_arg === 1){
_plot = new Plotattributes(_argCat,_argSize,_plotDen,_argAmount);
}
//create points
//PlotCategories = ['ring','disk','circle,'grid,'axis','row','axialSym','radialSym'];
if (_plot.category == 'ring'){
let radius = _plot.size - 250;
let diameter = floor(Math.PI *2 * radius);
_plot.amount = floor(diameter / 500);
for (let i = 0; i < _plot.amount; i++){
let tempT = (Math.PI*2/_plot.amount) * i
let tempR = radius;
_plot.x.push(tempR*Math.cos(tempT));
_plot.y.push(tempR*Math.sin(tempT));
}
}else if (_plot.category == 'disk'){
let diskMin = _plot.size * random(0,.7);
_plot.amount = _plotDen * (_plot.size - diskMin);
for (let i = 0; i < _plot.amount; i++){
let tempT = rList(1,0,Math.PI*2);
let tempR = rListWeight(1,diskMin,_plot.size,.5);
_plot.x.push(tempR*Math.cos(tempT));
_plot.y.push(tempR*Math.sin(tempT));
}
else if (_plot.category == 'circle'){
for (let i = 0; i < _plot.amount; i++){
let tempT = rList(1,0,Math.PI*2);
let tempR = rListWeight(1,0,_plot.size,.5);
_plot.x.push(tempR*Math.cos(tempT));
_plot.y.push(tempR*Math.sin(tempT));
}
}else if (_plot.category == 'grid'){
let gridScale = floor(random(300,800));
let gridAmount = _plot.size/gridScale;
for (let i = 0; i < gridAmount; i++){
for (let j = 0; j < gridAmount; j++){
let d = dist(i*gridScale, j*gridScale, 0, 0);
if(d <= _plot.size){
_plot.x.push(i*gridScale);
_plot.y.push(j*gridScale);
_plot.x.push(-i*gridScale);
_plot.y.push(j*gridScale);
_plot.x.push(i*gridScale);
_plot.y.push(-j*gridScale);
_plot.x.push(-i*gridScale);
_plot.y.push(-j*gridScale);
}
}
}
}else if (_plot.category == 'axis'){
let axisNum = ceil(random(2,8));
let gridScale = floor(random(200,300));
let gridAmount = floor(_plot.size/gridScale) ;
for (let i = 0; i < axisNum; i++){
for (let j = 2; j < gridAmount; j++){
let tempT = Math.PI*2*i/(axisNum);
let tempR = gridScale*j;
_plot.x.push(tempR*Math.cos(tempT));
_plot.y.push(tempR*Math.sin(tempT));
}
}
}else if (_plot.category == 'row'){
let gridScale = floor(random(300,400));
let gridAmount = _plot.size/gridScale;
for (let i = 0; i < gridAmount/2; i++){
for (let j = 0; j < gridAmount; j++){
let d = dist(i*gridScale*2, j*gridScale, 0, 0);
if(d <= _plot.size){
_plot.x.push(i*gridScale*2);
_plot.y.push(j*gridScale);
_plot.x.push(-i*gridScale*2);
_plot.y.push(j*gridScale);
_plot.x.push(i*gridScale*2);
_plot.y.push(-j*gridScale);
_plot.x.push(-i*gridScale*2);
_plot.y.push(-j*gridScale);
}
}
}
}else if (_plot.category == 'axialSym'){
for (let i = 0; i < _plot.amount/2; i++){
let tempT = rList(1,0,Math.PI);
let tempR = rListWeight(1,0,_plot.size,.5);
_plot.x.push(tempR*Math.cos(tempT));
_plot.y.push(tempR*Math.sin(tempT));
_plot.x.push(tempR*Math.cos(tempT));
_plot.y.push(-tempR*Math.sin(tempT));
}
}else if (_plot.category == 'radialSym'){
for (let i = 0; i < _plot.amount/8; i++){
let tempT = rList(1,0,Math.PI/4);
let tempT2 = rList(1,Math.PI/4,Math.PI/2);
let tempR = rListWeight(1,0,_plot.size,.5);
_plot.x.push(tempR*Math.cos(tempT));
_plot.y.push(tempR*Math.sin(tempT));
_plot.x.push(tempR*Math.cos(tempT));
_plot.y.push(-tempR*Math.sin(tempT));
_plot.x.push(-tempR*Math.cos(tempT));
_plot.y.push(tempR*Math.sin(tempT));
_plot.x.push(-tempR*Math.cos(tempT));
_plot.y.push(-tempR*Math.sin(tempT));
_plot.x.push(tempR*Math.cos(tempT2));
_plot.y.push(tempR*Math.sin(tempT2));
_plot.x.push(tempR*Math.cos(tempT2));
_plot.y.push(-tempR*Math.sin(tempT2));
_plot.x.push(-tempR*Math.cos(tempT2));
_plot.y.push(tempR*Math.sin(tempT2));
_plot.x.push(-tempR*Math.cos(tempT2));
_plot.y.push(-tempR*Math.sin(tempT2));
}
}else{
_plot.x.push(0);
_plot.y.push(0);
}
_plot.amount = _plot.x.length;
return(_plot);
}
function rList(length, low, high) {
let myList = []
for(let i=0; i<length; i++){
myList.push(random(low,high));
}
return myList
}
Stack generation code
////////////////// Aranda\lasch
////////////////// Jesse Bassett
////////////////// 5/20/2022 v3.3
function roll() {
makeStack();
}
class Stackattributes{
constructor() {
this.name,
this.x,//x position
this.y,//y position
this.category,//type of stacks to generate
this.stoneAmount = [],//how many stones in the stack
this.stoneLength = [],//list of stone lenghts
this.stoneWidth = [],//list of stone Widths
this.stoneHeight = [],//list of stone Heights
this.colors = [],//list of stone colors
this.rotation = [],//list of stone rotations
}
}
function makeStack(){
let stackCat = shuffle(stackCategories)[0];
let vList = new Array();
// print('Plot: ' + plot.category + ', Stack: ' + stackCat);
for(let i = 0; i < 30 ; i++){//voronoi list to use, sort by area later
vList.push(i);
}
for (let i = 0; i < plot.amount ; i++) {
stackList.push(new Stackattributes());
stackList[i].name = i;
stackList[i].category = stackCat;
//stackList[i].category = 'regular'
}
//let stackCategories = ['regular','tall','short','big','long','thin','sorted','centered','bowl','cone'];
for (let i = 0; i < stackList.length ; i++) {
if (stackList[i].category == 'regular'){
stackList[i].stoneAmount = floor(random(2,7));
stackList[i].stoneLength = rList(stackList[i].stoneAmount,100,250);
stackList[i].stoneWidth = rList(stackList[i].stoneAmount,100,250);
stackList[i].stoneHeight = rList(stackList[i].stoneAmount,50,150);
stackList[i].rotation = rList(stackList[i].stoneAmount,0,Math.PI/2);
stackList[i].VoronoiIndex = shuffle(vList);
}else if (stackList[i].category == 'short'){
stackList[i].stoneAmount = floor(random(2,4));
stackList[i].stoneLength = rList(stackList[i].stoneAmount,200,500);
stackList[i].stoneWidth = rList(stackList[i].stoneAmount,200,500);
stackList[i].stoneHeight = rList(stackList[i].stoneAmount,75,100);
stackList[i].rotation = rList(stackList[i].stoneAmount,0,Math.PI/2);
stackList[i].VoronoiIndex = shuffle(vList);
}else if (stackList[i].category == 'large'){
stackList[i].stoneAmount = floor(random(1,2));
stackList[i].stoneLength = rList(stackList[i].stoneAmount,150,300);
stackList[i].stoneWidth = rList(stackList[i].stoneAmount,150,300);
stackList[i].stoneHeight = rList(stackList[i].stoneAmount,200,600);
stackList[i].rotation = rList(stackList[i].stoneAmount,0,Math.PI/2);
stackList[i].VoronoiIndex = shuffle(vList);
}else if (stackList[i].category == 'long'){
stackList[i].stoneAmount = floor(random(4,6));
stackList[i].stoneLength = rList(stackList[i].stoneAmount,50,150);
stackList[i].stoneWidth = rList(stackList[i].stoneAmount,100,500);
stackList[i].stoneHeight = rList(stackList[i].stoneAmount,50,150);
stackList[i].rotation = rList(stackList[i].stoneAmount,0,Math.PI/2);
stackList[i].VoronoiIndex = shuffle(vList);
}else if (stackList[i].category == 'thin'){
stackList[i].stoneAmount = floor(random(9,15));
stackList[i].stoneLength = rList(stackList[i].stoneAmount,150,200);
stackList[i].stoneWidth = rList(stackList[i].stoneAmount,150,200);
stackList[i].stoneHeight = rList(stackList[i].stoneAmount,35,70);
stackList[i].rotation = rList(stackList[i].stoneAmount,0,Math.PI/2);
stackList[i].VoronoiIndex = shuffle(vList);
}else if (stackList[i].category == 'tall'){
stackList[i].stoneAmount = floor(random(1,6));
stackList[i].stoneLength = rList(stackList[i].stoneAmount,100,200);
stackList[i].stoneWidth = rList(stackList[i].stoneAmount,100,200);
stackList[i].stoneHeight = rList(stackList[i].stoneAmount,100,500);
stackList[i].rotation = rList(stackList[i].stoneAmount,0,Math.PI/2);
stackList[i].VoronoiIndex = shuffle(vList);
}
}
for (let i = 0; i < stackList.length ; i++) {
stackList[i].x = plot.x[i];
stackList[i].y = plot.y[i];
}
}