Public
Edited
May 9, 2024
2 forks
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
document.getElementById('routeSelect').addEventListener('change', function() {
handleRouteSelection(this.value);
});

Insert cell
document.getElementById('routeSelect').addEventListener('change', function() {
handleRouteSelection(this.value);
const selectedRoute = routes.find(route => route.name === this.value);
if (selectedRoute) {
const crimes = filterCrimesByRoute(selectedRoute); // Assume this function fetches crimes
drawRouteVisualization(selectedRoute, crimes, 800); // Assuming SVG width of 800
}
});

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
worseroute
Insert cell
findbounds(worseroute)
Insert cell
Insert cell
Insert cell
workbook = FileAttachment("RouteSample.xlsx").xlsx()
Insert cell
routeSample = workbook.sheet(0, {
headers: false,
// range: "A1:J10"
})
Insert cell
WorseRoute.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
TCBroad = FileAttachment("routeTCBroad@2.csv").csv()
Insert cell
TCAm = FileAttachment("routeTCAm@2.csv").csv()
Insert cell
CleryNewCats.csv
Type SQL, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
Insert cell
import {Legend, Swatches} from "@d3/color-legend"
Insert cell
groupedCrimes = crimes.map(function(crime) {
if (crime === "Attempted Robbery") {
return "Robbery";
} else if (crime === "Motorcycle Theft") {
return "Motor Vehicle Theft";
} else if (crime === "Burglary Pattern") {
return "Burglary";
} else {
return crime;
}
});
Insert cell
adjustedColorList = colorList.filter((color, index) => index !== 1 && index !== 11);
Insert cell
colorList = ["#4e79a7","#f28e2c","#e15759","#76b7b2","#59a14f","#edc949","#af7aa1","#ff9da7","#9c755f","#bab0ab", "#d16f9b", "#6f6dc7"];
Insert cell
colorScheme = d3.scaleOrdinal(crimes, adjustedColorList);
Insert cell
Insert cell
columbia_university = FileAttachment("Columbia_University.geojson").json()
Insert cell
Insert cell
Insert cell
smallCrimeData = FileAttachment("ManhattanCrimesSmall.csv").csv()
Insert cell
cityCrimeData = FileAttachment("ManhattanCrimes.csv").csv()
Insert cell
// snake code
L.Polyline.include({

// Hi-res timestamp indicating when the last calculations for vertices and
// distance took place.
_snakingTimestamp: 0,

// How many rings and vertices we've already visited
// Yeah, yeah, "rings" semantically only apply to polygons, but L.Polyline
// internally uses that nomenclature.
_snakingRings: 0,
_snakingVertices: 0,

// Distance to draw (in screen pixels) since the last vertex
_snakingDistance: 0,

// Flag
_snaking: false,


/// TODO: accept a 'map' parameter, fall back to addTo() in case
/// performance.now is not available.
snakeIn: function(){

if (this._snaking) { return; }

if ( !('performance' in window) ||
!('now' in window.performance) ||
!this._map) {
return;
}

this._snaking = true;
this._snakingTime = performance.now();
this._snakingVertices = this._snakingRings = this._snakingDistance = 0;

if (!this._snakeLatLngs) {
this._snakeLatLngs = L.LineUtil.isFlat(this._latlngs) ?
[ this._latlngs ] :
this._latlngs ;
}

// Init with just the first (0th) vertex in a new ring
// Twice because the first thing that this._snake is is chop the head.
this._latlngs = [[ this._snakeLatLngs[0][0], this._snakeLatLngs[0][0] ]];

this._update();
this._snake();
this.fire('snakestart');
return this;
},


_snake: function(){

var now = performance.now();
var diff = now - this._snakingTime; // In milliseconds
var forward = diff * this.options.snakingSpeed / 1000; // In pixels
this._snakingTime = now;

// Chop the head from the previous frame
this._latlngs[ this._snakingRings ].pop();

return this._snakeForward(forward);
},

_snakeForward: function(forward) {

// If polyline has been removed from the map stop _snakeForward
if (!this._map) return;
// Calculate distance from current vertex to next vertex
var currPoint = this._map.latLngToContainerPoint(
this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ]);
var nextPoint = this._map.latLngToContainerPoint(
this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices + 1 ]);

var distance = currPoint.distanceTo(nextPoint);

// console.log('Distance to next point:', distance, '; Now at: ', this._snakingDistance, '; Must travel forward:', forward);
// console.log('Vertices: ', this._latlngs);

if (this._snakingDistance + forward > distance) {
// Jump to next vertex
this._snakingVertices++;
this._latlngs[ this._snakingRings ].push( this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ] );

if (this._snakingVertices >= this._snakeLatLngs[ this._snakingRings ].length - 1 ) {
if (this._snakingRings >= this._snakeLatLngs.length - 1 ) {
return this._snakeEnd();
} else {
this._snakingVertices = 0;
this._snakingRings++;
this._latlngs[ this._snakingRings ] = [
this._snakeLatLngs[ this._snakingRings ][ this._snakingVertices ]
];
}
}

this._snakingDistance -= distance;
return this._snakeForward(forward);
}

this._snakingDistance += forward;

var percent = this._snakingDistance / distance;

var headPoint = nextPoint.multiplyBy(percent).add(
currPoint.multiplyBy( 1 - percent )
);

// Put a new head in place.
var headLatLng = this._map.containerPointToLatLng(headPoint);
this._latlngs[ this._snakingRings ].push(headLatLng);

this.setLatLngs(this._latlngs);
this.fire('snake');
L.Util.requestAnimFrame(this._snake, this);
},

_snakeEnd: function() {

this.setLatLngs(this._snakeLatLngs);
this._snaking = false;
this.fire('snakeend');

}

});


L.Polyline.mergeOptions({
snakingSpeed: 200 // In pixels/sec
});




L.LayerGroup.include({

_snakingLayers: [],
_snakingLayersDone: 0,

snakeIn: function() {

if ( !('performance' in window) ||
!('now' in window.performance) ||
!this._map ||
this._snaking) {
return;
}


this._snaking = true;
this._snakingLayers = [];
this._snakingLayersDone = 0;
var keys = Object.keys(this._layers);
for (var i in keys) {
var key = keys[i];
this._snakingLayers.push(this._layers[key]);
}
this.clearLayers();

this.fire('snakestart');
return this._snakeNext();
},


_snakeNext: function() {


if (this._snakingLayersDone >= this._snakingLayers.length) {
this.fire('snakeend');
this._snaking = false;
return;
}

var currentLayer = this._snakingLayers[this._snakingLayersDone];

this._snakingLayersDone++;

this.addLayer(currentLayer);
if ('snakeIn' in currentLayer) {
currentLayer.once('snakeend', function(){
setTimeout(this._snakeNext.bind(this), this.options.snakingPause);
}, this);
currentLayer.snakeIn();
} else {
setTimeout(this._snakeNext.bind(this), this.options.snakingPause);
}


this.fire('snake');
return this;
}

});


L.LayerGroup.mergeOptions({
snakingPause: 200
});
Insert cell
campusCrimes = FileAttachment("ManhattanCrimesCampusRegion@1.csv").csv()
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