Public
Edited
Jul 25, 2024
Insert cell
Insert cell
chart = {
const width = 900,//pixel size of the map
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width-50, height-10]);

// Use Mercator projection
var projection = d3
.geoMercator()//projection system used
.fitSize([width, height], finalBoundingBox);//out bounding box is here

var path = d3.geoPath().projection(projection);//need one of these for each line layer from qgis
var path2 = d3.geoPath().projection(projection);
var path3 = d3.geoPath().projection(projection);
var path4 = d3.geoPath().projection(projection);
var path5 = d3.geoPath().projection(projection);


var g = svg.selectAll('g').attr("id", "paths");//qgis lines variable //one variable for each geometry type
var c = svg.selectAll("circle")//for circles
var p = svg.selectAll("polyline")//for polylines from rhino
var t = svg.selectAll("text")
var l = svg.selectAll("line")



//static lines from qgis
//staticLines(path3, subways.features,"none",1,.5,"rgb(180,180,180)")
staticLines(path4, parks.features,"rgb(0,0,0)",'.1','.1',"rgb(255,0,0)")
staticLines(path5, dining_lines.features,"none",'0','1',"rgb(0,0,0)")
staticLines(path5, subwayL1.features,"none",'1','1',"rgb(255,0,0)")
staticLines(path5, roads.features,"none",'.25','.4',"rgb(0,0,0)")
staticLines(path5, frame.features,"none",'1','1',"rgb(255,0,0)")

function staticLines(path, data, sfill, sOpac, sW, stroke){

g.enter().append("path")
.data(data) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr("d", path) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", sfill)
.style('stroke-opacity',sOpac)
.style("stroke-width", sW)
.style("stroke", stroke)
}


//static points from qgis
staticCircles(restrooms.features,'2','black','1',"0")
staticCircles(theaters.features,'0','blue','1',"0")
staticCircles(affordHousingPoints.features,'1.5','black','1',"0")
staticCircles(fireHouse.features,'1','red','1',"0")
staticCircles(subwayStationPoints.features,'2.5','black','1',"0")

function staticCircles(data,r,sfill, sOpac, sWidth){

c.enter().append('circle')
.data(data) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('cx',function(d) {return path.centroid(d)[0]})
.attr("cy",function(d) {return path.centroid(d)[1]})
.attr('r', r)
.attr('fill', sfill)
.style('fill-opacity',sOpac)
.style("stroke-width", sWidth)
}


//lines from rhino
polyline(pathLines,'none','.5','.5','red')
polyline(oriLines,'none','.5','.25','red')
polyline(box1,'rgb(255,255,255)','2','.5','black')
polyline(b1,'none','.5','1.1','black')
polyline(s1,'none','.5','0.25','red')
polyline(m1,'none','.5','0.6','black')
polyline(title,'rgb(0,0,0)','.5','0.6','black')
polyline(titlehide,'rgb(255,255,255)','.5','0.6','black')


function polyline(data, sfill, sOpac, sW, stroke){

g.enter().append("polyline")
.data(data) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", sfill)
.style('stroke-opacity',sOpac)
.style("stroke-width", sW)
.style("stroke", stroke)
}

p.enter().append("polyline")
.data(firehouse) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", icon1) //The d attribute defines a path to be drawn, only applies to appended elements
.attr('transform',function(d) {return 'translate('+projection([d.Long,d.Lat])[0]+','+projection([d.Long,d.Lat])[1]+')'})
.style("fill", 'none')
.style("stroke-width", '.35')
.style("stroke", 'red')
.on("mouseover", addText)
.on("mouseout", addText2)

p.enter().append("polyline")
.data(zone1) //get data to define path
.enter()
.append('polyline')
.attr("points", function(d) {return d})
.style("fill", 'white')
.style('fill-opacity','0')
.style("stroke-width", '1')
.style("stroke", 'black')
.style('stroke-dasharray','2 2')
.on("mouseover", addWireframe)
.on("mouseout", removeWireframe)

p.enter().append("polyline")
.data(box222) //get data to define path
.enter()
.append('polyline')
.attr("points", function(d) {return d})
.style("fill", 'white')
.style('fill-opacity','.65')
.style("stroke-width", '.1')
.style("stroke", 'none')

function addWireframe(event,d){

p.enter().append("polyline")
.data(wireframe1) //get data to define path
.enter()
.append('polyline')
.attr('class','wireframe')
.attr("points", function(d) {return d})
.style("fill", 'none')
.style("stroke-width", '.5')
.style("stroke", 'black')

svg//draw text
.append("text") //appends path to data
.attr('class','mText')
.attr('x',10)
.attr("y",590)
.attr('fill', 'black')
.style('font-family','helvetica')
.style("font-size", "8px")
.text('Fire Suppression Powder Compartment & Nozzle')
}
function removeWireframe(event,d){
svg.selectAll('polyline.wireframe').remove()
svg.selectAll('text').remove()
}


//zone2
p.enter().append("polyline")
.data(zone2) //get data to define path
.enter()
.append('polyline')
.attr("points", function(d) {return d})
.style("fill", 'white')
.style('fill-opacity','0')
.style("stroke-width", '1')
.style("stroke", 'black')
.style('stroke-dasharray','2 2')
.on("mouseover", addWireframe2)
.on("mouseout", removeWireframe2)
function addWireframe2(event,d){

p.enter().append("polyline")
.data(wireframe2) //get data to define path
.enter()
.append('polyline')
.attr('class','wireframe')
.attr("points", function(d) {return d})
.style("fill", 'none')
.style("stroke-width", '.5')
.style("stroke", 'black')

svg//draw text
.append("text") //appends path to data
.attr('class','mText')
.attr('x',10)
.attr("y",590)
.attr('fill', 'black')
.style('font-family','helvetica')
.style("font-size", "8px")
.text('Fuel Storage Compartment & Engine Exhaust Nozzle')
}
function removeWireframe2(event,d){
svg.selectAll('polyline.wireframe').remove()
svg.selectAll('text').remove()
}



//zone3
p.enter().append("polyline")
.data(zone3) //get data to define path
.enter()
.append('polyline')
.attr("points", function(d) {return d})
.style("fill", 'white')
.style('fill-opacity','0')
.style("stroke-width", '1 ')
.style("stroke", 'black')
.style('stroke-dasharray','2 2')
.on("mouseover", addWireframe31)
.on("mouseout", removeWireframe31)
function addWireframe31(event,d){

p.enter().append("polyline")
.data(wireframe5) //get data to define path
.enter()
.append('polyline')
.attr('class','wireframe')
.attr("points", function(d) {return d})
.style("fill", 'none')
.style("stroke-width", '.5')
.style("stroke", 'black')

svg//draw text
.append("text") //appends path to data
.attr('class','mText')
.attr('x',10)
.attr("y",590)
.attr('fill', 'black')
.style('font-family','helvetica')
.style("font-size", "8px")
.text('Engine & Iertial Gyroscope')
}
function removeWireframe31(event,d){
svg.selectAll('polyline.wireframe').remove()
svg.selectAll('text').remove()
}



//zone4
p.enter().append("polyline")
.data(zone4) //get data to define path
.enter()
.append('polyline')
.attr("points", function(d) {return d})
.style("fill", 'white')
.style('fill-opacity','0')
.style("stroke-width", '1')
.style("stroke", 'black')
.style('stroke-dasharray','2 2')
.on("mouseover", addWireframe41)
.on("mouseout", removeWireframe41)
function addWireframe41(event,d){

p.enter().append("polyline")
.data(wireframe41) //get data to define path
.enter()
.append('polyline')
.attr('class','wireframe')
.attr("points", function(d) {return d})
.style("fill", 'none')
.style("stroke-width", '.5')
.style("stroke", 'black')

svg//draw text
.append("text") //appends path to data
.attr('class','mText')
.attr('x',10)
.attr("y",590)
.attr('fill', 'black')
.style('font-family','helvetica')
.style("font-size", "8px")
.text('Engine & Iertial Gyroscope')
}
function removeWireframe41(event,d){
svg.selectAll('polyline.wireframe').remove()
svg.selectAll('text').remove()
}








//display names from spreadsheet - use this format for points from SPREADSHEET
t.enter().append('text')
.data(firehouse) //get data to define path
.enter() //there are more data than elements, this selects them
.append("text") //appends path to data
//.attr('class','spots')
.attr('x',200)
.attr("y",function(d,i){return 680 +(i*16)})
.attr('fill', 'black')
.style('font-family','helvetica')
.style("font-size", "9px")
.style("text-anchor", "end")
.text(function(d){return d.Name})
.on("mouseover",musText)
.on("mouseout",removeMusText)

function removeMusText(event,d){
svg.selectAll("line.museumLine").remove()
//svg.selectAll('polyline.bunny').style('fill','red')
svg.selectAll('polyline.angles').style('fill','red')
}

function musText(event,d){

//svg.selectAll('polyline.bunny').style('fill','yellow')
svg.selectAll('polyline.angles').style('fill','yellow')

//THESE ARE LINES FOR ANNOTATION
l.enter().append('line')
.data(firehouse) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','museumLine')
.attr('x1',200)
.attr("y1",680)
.attr('x2',projection([d.Long,d.Lat])[0])
.attr("y2",projection([d.Long,d.Lat])[1])
.attr('stroke', 'black')
.attr('stroke-width', '1.25')
.style('stroke-dasharray', '3 2')

//THESE ARE LINES FOR ANNOTATION
l.enter().append('line')
.data(firehouse) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','museumLine')
.attr('x1',200)
.attr("y1",function(d,i){return 680 +(i*16)})
.attr('x2',function(d) {return projection([d.Long,d.Lat])[0]-5})
.attr("y2",function(d,i){return 680 +(i*16)})
.attr('stroke', 'black')
.attr('stroke-width', '.55')
.style('stroke-dasharray', '3 2')

l.enter().append('line')
.data(firehouse) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','museumLine')
.attr('x1',function(d) {return projection([d.Long,d.Lat])[0]-5})
.attr("y1",function(d,i){return 680 +(i*16)})
.attr('x2',function(d) {return projection([d.Long,d.Lat])[0]-5})
.attr("y2",function(d) {return projection([d.Long,d.Lat])[1]+10})
.attr('stroke', 'black')
.attr('stroke-width', '.55')
.style('stroke-dasharray', '3 2')


}

t.enter().append('text')//theater names from QGIS - use this format for points from QGIS
.data(subways.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("text") //appends path to data
//.attr('class','spots')
.attr('x',function(d) {return path.centroid(d)[0]})
.attr("y",function(d) {return path.centroid(d)[1]-8})
.attr('fill', 'black')
.style('font-family','helvetica')
.style('text-anchor','middle')
.style("font-size", "6px")
.text(function(d){return d.properties.NAME})









//points from spreadsheet
c.enter().append('circle')
.data(firehouse) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class','spots')
.attr('cx',function(d) {return projection([d.Long,d.Lat])[0]})
.attr("cy",function(d) {return projection([d.Long,d.Lat])[1]})
.attr('r', .01)
//.attr('fill', 'red')
//.style('fill-opacity','1')
//.style("stroke-width", "1")
//.style("stroke", "black")
.on("mouseover", addText)
.on("mouseout", removeText)

function addText(event,d){

svg//draw text
.append("text") //appends path to data
.attr('class','mText')
.attr('x',projection([d.Long,d.Lat])[0]-15)
.attr("y",projection([d.Long,d.Lat])[1]-8)
.attr('fill', 'black')
.style('font-family','arial')
.style("font-size", "16px")
.style("stroke", "black")
.text(d.Name)
}

function addText2(event,d){

svg//draw text
.append("text") //appends path to data
.attr('class','mText')
.attr('x',projection([d.Long,d.Lat])[0]-15)
.attr("y",projection([d.Long,d.Lat])[1]-8)
.attr('fill', 'black')
.style('font-family','arial')
.style("font-size", "16px")
.style("stroke", "black")
.text(d.Name)
}

function removeText(){
svg.selectAll('text.mText').remove()
}




return svg.node();
}
Insert cell
Insert cell
firehouse = d3.csv(firehouseLink,d3.autoType)
Insert cell
finalBoundingBox = FileAttachment("Final Bounding Box.geojson").json()
Insert cell
boundingBoxNew = FileAttachment("Bounding Box New.geojson").json()
Insert cell
boundingBox = FileAttachment("bounding box.geojson").json()
Insert cell
mouth = FileAttachment("mouth.txt").tsv({array:true})
Insert cell
eyes = FileAttachment("eyes.txt").tsv({array:true})
Insert cell
face_outline = FileAttachment("face_outline.txt").tsv({array:true})
Insert cell
bbox_new = FileAttachment("bbox_new.geojson").json()
Insert cell
graphic_test = FileAttachment("graphic_test.txt").tsv({array:true})
Insert cell
bbox1 = FileAttachment("bbox@1.geojson").json()
Insert cell
theaters = FileAttachment("theaters.geojson").json()
Insert cell
restrooms = FileAttachment("restrooms.geojson").json()
Insert cell
subways = FileAttachment("subways.geojson").json()
Insert cell
parks = FileAttachment("parks.geojson").json()
Insert cell
dining_lines = FileAttachment("dining_lines.geojson").json()
Insert cell
Insert cell
spots = d3.csv(spotsLink,d3.autoType)
Insert cell
import { wrap_text, wrap_text_nchar } from "@ben-tanen/svg-text-and-tspan-word-wrapping"
Insert cell
subwayL1 = FileAttachment("Subway L 1.geojson").json()
Insert cell
roads = FileAttachment("Roads.geojson").json()
Insert cell
fireHouse = FileAttachment("Fire House.geojson").json()
Insert cell
subwayStationPoints = FileAttachment("subway station points.geojson").json()
Insert cell
frame = FileAttachment("Frame.geojson").json()
Insert cell
pathLines = FileAttachment("Path Lines.txt").tsv({array:true})
Insert cell
oriLines = FileAttachment("ori Lines.txt").tsv({array:true})
Insert cell
box = FileAttachment("box.txt").tsv({array:true})
Insert cell
b = FileAttachment("B.txt").tsv({array:true})
Insert cell
s = FileAttachment("S.txt").tsv({array:true})
Insert cell
icon1 = FileAttachment("icon1.txt").tsv({array:true})
Insert cell
m1 = FileAttachment("M1.txt").tsv({array:true})
Insert cell
box1 = FileAttachment("box1.txt").tsv({array:true})
Insert cell
s1 = FileAttachment("S1.txt").tsv({array:true})
Insert cell
b1 = FileAttachment("B1.txt").tsv({array:true})
Insert cell
zone1 = FileAttachment("Zone1.txt").tsv({array:true})
Insert cell
wireframe1 = FileAttachment("Wireframe1.txt").tsv({array:true})
Insert cell
zone2 = FileAttachment("Zone2.txt").tsv({array:true})
Insert cell
wireframe2 = FileAttachment("Wireframe2.txt").tsv({array:true})
Insert cell
zone3 = FileAttachment("Zone3.txt").tsv({array:true})
Insert cell
wireframe31 = FileAttachment("Wireframe31.txt").tsv({array:true})
Insert cell
wireframe5 = FileAttachment("Wireframe5.txt").tsv({array:true})
Insert cell
zone4 = FileAttachment("Zone4.txt").tsv({array:true})
Insert cell
wireframe41 = FileAttachment("Wireframe41.txt").tsv({array:true})
Insert cell
box222 = FileAttachment("box222.txt").tsv({array:true})
Insert cell
title = FileAttachment("Title.txt").tsv({array:true})
Insert cell
titlehide = FileAttachment("titlehide.txt").tsv({array:true})
Insert cell
affordHousingPoints = FileAttachment("Afford Housing Points.geojson").json()
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more