Published
Edited
Sep 28, 2020
1 fork
Insert cell
Insert cell
Insert cell
mutable globalZoom = 0

Insert cell
mutable globalTmp=0
Insert cell
mutable globalOTSize = 0
Insert cell
import {text, textarea} from "@jashkenas/inputs"
Insert cell
//import {textarea} from "@jashkenas/inputs"
Insert cell
import {checkbox, slider} from "@rohscx/inputs"
Insert cell
viewof frame_view = textarea({title: "Frame", placeholder:frame, description: "Frame data", width: "100%"})
Insert cell
mutable date_time = ""
Insert cell
viewof frame_date_time = text({title: "Date-time", placeholder:date_time, description: "Frame datetime"})
Insert cell
mutable frame_angle = ""
Insert cell
viewof frame_date_angle = text({title: "Wind direction", placeholder:frame_angle, description: "Frame wind angle"})
Insert cell
mutable frame_direction = "";

Insert cell
viewof frame_wind_sector = text({title: "Wind sector", placeholder:frame_direction, description: "Frame wind sector"})
Insert cell
mutable frame_velocity = "";

Insert cell
viewof frame_wind_velocity = text({title: "Wind speed", placeholder:frame_velocity, description: "Frame wind velocity"})
Insert cell
mutable frame_wind_color = "";
Insert cell
viewof frame_windcolor = text({title: "Wind color", placeholder:frame_wind_color, description: "Frame wind color"})
Insert cell
mutable frame= "";
Insert cell
viewof show_rects = checkbox({
title: 'Show source detection',
//description: 'Just a single checkbox to toggle',
options: [
{ value: 'toggle', label: 'Show' }
],
value: 'toggle'
})
Insert cell
//viewof show_rects = html`<input type=checkbox>`
Insert cell
viewof map123 = {
// Source coordinates.
var center = [10.342640, 43.57514];
var zoomLevelOnStart = 13.5
var geoReferenceWidthInMeters = 5000;
var geoReferenceHeightInMeters = 5000;
//var imageURL = "https://upload.wikimedia.org/wikipedia/commons/3/30/Vector-based_example.svg";
var container = html`<div id= "mapc" style="height:600px;" style="width=:600px">
<div id ="map2" style="height:600px" style="width:600px;" style="position:absolute;" ></div>
</div>`;
const svgc = d3.select(DOM.svg(10, 10));
svgc.append();
yield container; // Give the container dimensions.
var map = new mapboxgl.Map({
container: "map2",
center: center, //[10.342640, 43.57514],
pitchWithRotate: false,
//center: [43.57514,10.342640],
zoom: zoomLevelOnStart,
style: "mapbox://styles/mapbox/streets-v10",
scrollZoom: true
});

var centerShifted =[center[0],center[1]]
var svgContainer;
var markerContainer = document.createElement("div");
markerContainer.className = "markerz";
markerContainer.setAttribute("pointer-events","none");
Snap(markerContainer).append(odourTimeLaps);
svgContainer = odourTimeLaps;
new mapboxgl.Marker(markerContainer).setLngLat(centerShifted).addTo(map);
var marker = new mapboxgl.Marker()
.setLngLat(center)
.addTo(map);
var marker = new mapboxgl.Marker({color:'#B13FCE'})
.setLngLat(centerShifted)
.addTo(map)

function getScale(n, m) {
var center = map.getCenter();
var zoom = map.getZoom();
mutable globalZoom = zoom;
var tmp =
156543.03392 * Math.cos(center.lat * Math.PI / 180) / Math.pow(2, zoom);
mutable globalTmp = tmp;
var meterSizeInPixelN = n / tmp;
var meterSizeInPixelM = m / tmp;
return [meterSizeInPixelN, meterSizeInPixelM];
}

function render() {
var pixelSizes = getScale(
geoReferenceWidthInMeters,
geoReferenceHeightInMeters
);
markerContainer.style.width = pixelSizes[0] + "px";
markerContainer.style.height = pixelSizes[1] + "px";
mutable globalOTSize = markerContainer.style.width;
svgContainer && (svgContainer.style.transform = "rotate(" + -map.getBearing() + "deg)");
//console.log("rotate(" + -map.getBearing() + "deg)");
//console.log(svgContainer);
}

// re-render our visualization whenever the view changes
map.on("viewreset", render);
map.on("zoom", render);
map.on("drag", render);
map.on("rotate", render);

render();

//Disable rotation only for codepen demo, setting the style transform is also commented in render, this seems to be very slow in codepen embed. in general it works fine though..
// disable map rotation using right click + drag
//map.dragRotate.disable();
// disable map rotation using touch rotation gesture
//map.touchZoomRotate.disableRotation();
invalidation.then(() => map.remove());

}

Insert cell
d3 = require("d3@5")
Insert cell
//import {slider} from "@rohscx/inputs"
Insert cell
psv = d3.dsvFormat(",")
Insert cell
//Crea l’array di oggetti rawPerceptions che rappresenta il timelaps delle percezioni, ora per ora e recettore per recettore
rawPerceptions = d3.text('https://raw.githubusercontent.com/giulianogemma/master/master/timelaps_month2.csv').then(
(txt) => psv.parse(txt, d=>({
Frame: d.Frame,
DateTime: d.DateTime,
recettore: d.recettore,
Level: +d.Level,
color: d.color
})))
/* il file : timelaps_month2.csv'
è un file csv che contiene le informazioni timelaps, ovvero le percezioni ed un colore associato ad il livelo, ora per ora ad ogni recettore. Il file viene prodotto esternamente.
Features:
Frame: id del frame
DateTime: orario della percezione
recettore: recettore
Latitude: Latitudine traslata in (0,0) del recettore
Longitude: longitudine traslata in (0,0) del recettore
Level: livello di percezione
color, colore RGB associato al livello di percezione
*/
Insert cell
//Ricava con la funzione nest() l’elenco dei recettori dall'array rawPerceptions
recettori= d3.nest()
.key(function(d) { return d.recettore; })
.entries(rawPerceptions)
.map(d=> d.key)
//.sort(function (a,b) {return d3.ascending(a, b);})

Insert cell
//Ricava con la funzione nest() l’elenco delle date dall'array rawPerceptions
dates= d3.nest()
.key(function(d) { return d.DateTime; })
.entries(rawPerceptions)
.map(d=> d.key)
.sort(function (a,b) {return d3.ascending(a, b);})
Insert cell
// Larghezza del canvas
w = 800
Insert cell
// Altezza del canvas
h = 800
Insert cell
//Crea l’array rawWindDir, che contiene, per ogni ora, la direzione del vento.
// Il file wind_dir_flat_201906.csv' è creato esternamente
rawWindDir = d3.csv('https://raw.githubusercontent.com/giulianogemma/master/master/wind_dir_flat_201906.csv')
Insert cell
//Crea l’array rawWindVel, che contiene, per ogni ora, la velocità del vento.
rawWindVel = d3.csv('https://raw.githubusercontent.com/giulianogemma/master/master/wind_vel_flat_201906.csv')
// coords.csv è creato esternamente
Insert cell
//Crea l’array di oggetti mapData2, che contiene, per ogni recettore, le coordinate relative a (0,0) di ogni recettore.
mapData2 = d3.text("https://raw.githubusercontent.com/giulianogemma/master/master/coords.csv").then(
(txt) => psv.parse(txt,d=>({
name: d.recettore,
lon: +d.lon,
lat: +d.lat
})))
Insert cell

dataset2 = {
const nodes = mapData2.map(d => ({name:d.name,
id:mapData2.indexOf(d)
}))

nodes.forEach(function (n){
const lat = (mapData2.find(x => x.name ==n.name)) ? mapData2.find(x => x.name ==n.name).lat : 200
const lon = (mapData2.find(x => x.name ==n.name)) ? mapData2.find(x => x.name ==n.name).lon : 200
n['lat']=lat
n['lon']=lon
n['x']= xScale2(lon)/* +40*/
n['y']= yScale2(lat) /*+20*/
n['color'] = '#00ff00'
});
const edges = []
const data = {}
data['nodes']=nodes
data['links']=edges
return data
}
Insert cell
// ext2 è un oggetto che contiene le estenzioni il latitudine (lat) e longitudine (lon)
// ricavate dall'oggetto mapData2.
// serve come riferimento delle funzioni successive di scalatura
ext2 = ({
lat: d3.extent(mapData2,d=>+d.lat),
lon: d3.extent(mapData2, d => +d.lon)
})
Insert cell
// effettua una trasformazione in scala rispetto all'ampiezza del canvas delle longitudini
xScale2 = d3.scaleLinear()
.domain(ext2.lon)
//.range([0, (w-40)/2 /* - margin.r - margin.l -20*/]);
.range([0, (w)/2 /* - margin.r - margin.l -20*/]);

Insert cell
xScale2(ext2.lon[1]);
Insert cell
// map a latidude wrt the center of the canvas
// effettua una trasformazione in scala rispetto all'ampiezza del canvas delle latiutudini
yScale2 = d3.scaleLinear()
.domain(ext2.lat)
//.range([(h-40)/2 /*- margin.t -margin.b*/, 0 /*margin.t*/]);
.range([(h)/2 /*- margin.t -margin.b*/, 0 /*margin.t*/]);
Insert cell
yScale2(0)
Insert cell
ext2
Insert cell
yScale2(ext2.lat[0])
Insert cell
// determina le estensioni delle velocità del vento
extVel = ({
vel: d3.extent(rawWindVel,d=>+d.velocity),
});
Insert cell
// blowLen è usata per determinare la lunghezza della rappresentazione del soffio di vento.
// effettua una trasformazione in scala a partire dalla velocità del vento
// in modo che la lungherzza sia proporzionale alla velocità del vento.
blowLen = d3.scaleLinear()
.domain(extVel.vel)
.range([0.33,2]);
//wind_color = myColor(velocity)
Insert cell
// min_wind_vel è la velocità minima del vento
min_wind_vel=d3.min(rawWindVel, function(d) { return +d.velocity; })
Insert cell
// max_wind_vel: è la velocità massima del vento
max_wind_vel= d3.max(rawWindVel, function(d) { return +d.velocity; })
Insert cell
xScale2(0)
Insert cell
yScale2(0)
Insert cell
odourTimeLaps = {

// crea un oggetto svg di larghezza w ed altezza h
// (0,0) è il punto in alto a sinistra
const svg = d3.select(DOM.svg(w, h));
svg.attr("width", w /*+ margin.l + margin.r*/)
.attr("height", h /* + margin.t + margin.b*/)
//.append("g")
//.attr("transform", `translate(${margin.l},${margin.t})`)
;
// aggiunge una cornice rettangolare all'oggetto svg con le stesse dimensioni di svg.
// serve ad evidenziare il canvas principale
svg.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', w /*+ margin.l + margin.r*/)
.attr('height', h /*+ margin.t + margin.b*/)
.style('stroke',"black")
.style("stroke-width",1)
.attr('opacity', 0.1)
.attr("class", "border");;
;
// percContainer is the container who envelopes the receptor icon
// Crea un gruppo , a cui si fa riferimento con la variabile percContainer, che è il contenitore dei recettori.
var percContainer = svg.append("g")
//.attr("transform", "translate(" + w/3 + "," + h/3 + ")")
.attr("transform", "translate(" + (xScale2(0) /*+margin.l*/) + ","+(yScale2(0) /*+margin.t*/)+ ")");
//.attr("transform", "translate(" + (w/2) + ","+(h/2)+ ")");
// blowL è la larghezza delle aree quadrate che contengono le visualizzazioni dei soffi
var blowL=30;
// borderVisibility: variabile per la visualizzazione dei bordi degli oggetti blow
var borderVisibility = "hidden"; //"visible";

// Initialize the odour source node
// La sorgente è rappresentata da un cerchio rosso al centro del canvas
const center = svg.append("g")
//.attr("class", "nodes")
.attr('stroke', "#ff0000")
.selectAll("circle")
//.data([ xScale2(0) -(w/2)/*+40*/,yScale2(0)-(h/2)/*+20*/])
.data([200,/*+40*/200/*+20*/])
.enter()
.append("circle")
.attr('fill','#cccccc')
.attr("r",10)
.attr("cx", (w/2)/* +margin.l*/)
.attr("cy", (h/2)/* + margin.t*/)
;
var percC = percContainer.selectAll("g.recettore")
.data(dataset2.nodes)
.enter()
.append("g")
.attr("class", "recettore")
.each(function(d, i) {
var cn = d.name
cn = cn.replace(/ /g,"")
//console.log(cn);
d3.select(this)
.attr("class", cn)
.attr('stroke', "#00ff00")
//.attr('fill' ,"none")
.append("circle")
//.attr('fill','none')
.attr("r",10);
}); //each percC container
// initilize the blowing wind represented by the rotating outer arc from source
let xSource = xScale2(0)
let sector =svg.append("path")
.attr("transform", "translate ("+(xScale2(0)/*+40*/)+", "+(yScale2(0)/*+20*/)+")")
.attr("d", d3.arc()
.innerRadius( 15 )
.outerRadius( 150 )
.startAngle (-Math.PI/12 ) // It's in radian, so Pi = 3.14 = bottom.
.endAngle( Math.PI/12 ) // 2*Pi = 6.28 = top
)
.attr('stroke', 'black')
.attr('fill', '#1010ff')
.attr('opacity', 0.5);
// add an inner arc, representing the theta spread angle ov view from source
let wind =svg.append("path")
.attr("transform", "translate("+(xScale2(0)/*+40*/)+", "+(yScale2(0)/*+20*/)+")")
.attr("d", d3.arc()
.innerRadius( 15 )
.outerRadius( 150 )
.startAngle (-Math.PI/24 ) // It's in radian, so Pi = 3.14 = bottom.
.endAngle( Math.PI/24 ) // 2*Pi = 6.28 = top
)
.attr('stroke', 'black')
.attr('fill', '#69b3a2')
.attr('opacity', 0.3);
// Text for date
const date = svg.append("g")
.attr("class", "text")
.selectAll("text")
.data([ xScale2(0) -(w/2)+40,yScale2(0)-(h/2)+20])
.enter().append("text")
//.text("Hello")
.style("fill","black")
.style("font-size","15px")

// Text to perceptors nodes
const text = svg.append("g")
.attr("class", "text")
.selectAll("textr")
.data(dataset2.nodes)
.enter().append("text")
.text(d => d.name)
.style("fill","white")
.style("font-size","5px")

var ww = 830, hw = 830;
var t0 = Date.now();
var blows=[]
//var blowL =30 //edge length of blow object
var cy = 30;
var cx = 30;
var gap=0;
var ph =1
// var borderVisibility = "visible";//"hidden";//"visible"
// costruisce la griglia del vento
// Ricordarsi che un oggetto blow può essere amplificato con blowLen in un range da 0.33 a 2
// Praticamente si crea una griglia 16 X 16
// Per ogni riga pari si piazzano 8 blow
// Ogni 4 righe, a partire dalla seconda, si sfasano di 60 px
// viene creato l'array blows che contiene le coordinate ed i parametri di oggni oggetto blow
for (var i = 0; i < 16; i++) {
if(i%2==0){
if(i%4 ==2){
cx+=2*blowL
}//if(i%4 ==2)
for(var j =0; j < 16; j++){
if(j%2==0){
blows.push({ centery: cy, centerx: cx ,R: 70, r: 5, speed: 2, phi0: 0});
//console.log(i,j,cx,cy)
}//if(j%2==0)
cx+=(2*blowL + gap)
}//for j
cx =30;
}//if(i%2==0)
cy+=(2*blowL + gap)
} // for i
/*var blows = [
{ center: 50, R: 70, r: 5, speed: 2, phi0: 90},
{ center: 150, R: 50, r: 10, speed: 2, phi0: 90}
];*/
// Crea il contenitore degli oggetti blow
var blowContainer = svg.append("g")
//.attr("transform", "translate(" + w/3 + "," + h/3 + ")")
//.attr("transform", "translate(" + 0 + ","+ 0 + ")")
//Insertisce nel container blowContainer gli oggetti (grupp gi) blow secondo l'array blow
// Ad ogni oggetto blow viene aggiunto un bordo quadrato blowBorder di tipo path
// Ad ogni oggetto blow viene aggiunto una sinusoide besier con frecciA blowArrow di tipo path
// LA FRECCIA È INIZIALMENTE RIVOLTA VERSO IL BASSO
var blowC = blowContainer.selectAll("g.blow")
.data(blows)
.enter()
.append("g")
.attr("class", "blow")
.each(function(d, i) {
d3.select(this).append("path").attr("class", "blowBorder")
.attr("fill", "none")
.attr("stroke", "blue")
.attr("stroke-width", "1")
.attr("opacity", 1)
.attr("visibility", borderVisibility)
.attr("d", function(d) {
return"M-"+(blowL)+",-"+blowL+" L"+blowL+",-"+blowL+" L"+blowL+","+blowL+", L-"+blowL+","+blowL+", L-"+blowL+",-"+blowL+""; });
// moving shape
d3.select(this)
.append("path")
.attr("d", "M0, -25 Q11, -12.5 0,0 T0,25 M0,33 L-3,25 L3,25 Z")
.attr("fill", "none")
.attr("stroke", "blue")
.attr("stroke-width", "3")
.attr("opacity", 1)
.attr("class", "blowArrow")
.attr("transform", "rotate(180)") ;
}); //each blowContainer
// blowA seleziona tutti gli ogggetti frecce di classe blowArrow
var blowA = blowContainer.selectAll(".blowArrow")
var tickWind =0; // tickWind viene usata per modellare la curva della freccia del vento.
//E' un valore ciclico
//parte da 0 si incremeta fino a size, per poi decemetare fino -size e reincremetarsi
var inc=1;
var lengthB = 1
var tickInc =0.1
var tickL =0.3 // tickL oscilla tra 0.3 ed 1 con incrementi di 0.1
// Set the timer for frame animation
// animationSpeed è regolata dallo slider
// ticked() is invoked on a particular time delay interval (animationSpeed). If delay is not specified, it takes the timer time.
var t = d3.interval(ticked, animationSpeed);
var tick = 0 // tick è il contatore dei frames. E' l'indice che scorre per indicizzare gli array delle date, delle velocità, delle direzioni dei venti.
// tick si incrementa di una unità ad ogni delay interval e viene resettato a zero quando supera
// la lunghezza dell'array delle date (ha spazzato tutti i frames)
let outerTick=0;
var rotate = 0;
var rotateBlow = 0;
var direction = "";
var velocity = 0;
var wind_color = "#000000";
var blowLength = 0;
var blowTick =0;
function ticked() {
//vars for wind field
var delta = (Date.now() - t0);
var start =0;
var end =0;
var sin = 0;
// size E
var size=15
//************************
//controllo di tickWind
tickWind+=inc
if (tickWind >= size){
inc *= -1
}
if (tickWind <= -size ){
inc *= -1
}
//**********************
//if(tickWind%10==0){
//**********************
//controllo di tickL
tickL+=tickInc;
if (tickL >= 1){
tickInc *= -1
}
if (tickL <= 0.3 ){
tickInc *= -1
}
//***********************
//}
//svg.selectAll(".blow")
// Animazione. Sposta tutti i blows da (0,0) fino le coordinate stabilite nell'array blows
// tutto è relativo al canvas principale
blowC.transition()
.attr("transform", function(d) {
//return "translate("+d.centerx+","+d.centery+") rotate(" + d.phi0 + delta * d.speed/200 + ") scale("+tickL+" "+tickL+")";
return "translate("+d.centerx+","+d.centery+") rotate(" + (rotateBlow) + ") scale("+blowLength+" "+blowLength+")";
})
.duration(animationSpeed/2);
/*svg.selectAll(".blowArrow")
.attr("d", function(d){return "M0, -25 Q"+tickWind+",-12.5 0,0 T0,25 M0,30 L-3,25 L3,25 L0,30"})*/
//Animazione. Fa scillare gli oggetti freccia
blowA.transition()
.attr("d", function(d){return "M0, -25 Q"+tickWind+",-12.5 0,0 T0,25 M0,33 L-3,25 L3,25 Z"})
.attr("stroke", wind_color)
.duration(animationSpeed/2);
//end of vars for wind field
// node.attr("fill", d3.hsl(tick,100,50))
// Animazione, porta i recettori al loro posto
percC.transition()
.attr("transform", function(d) {
return "translate("+(d.x -(xScale2(0) +(xScale2(0)-(w/2)) /*+40*/))+","+( d.y -(yScale2(0)+(yScale2(0)-(h/2))/*+20*/))+")";
})
.duration(animationSpeed/2);
// center.attr("cx", xScale2(0)-(xScale2(0)-(w/2))/* +margin.l*/)
// .attr("cy", yScale2(0)-(yScale2(0)-(h/2))/* + margin.t*/)
// Muove la sorgente al suo posto
center.transition()
.attr("cx", (w/2)/* +margin.l*/)
.attr("cy", (h/2)/* + margin.t*/)
.duration(animationSpeed/2);
text.attr("x", d => d.x - 5-(xScale2(0)-(w/2))) //position of the lower left point of the text
.attr("y", d => d.y /*+ 5*/ -(yScale2(0)-(h/2))); //position of the lower left point of the text
date.attr("x", 40) //position of the lower left point of the text
.attr("y", 20) //position of the lower left point of the text
//.text(dates[tick]+" - Wind direction:"+rotate+"° Wind sector: "+direction + " - Wind speed: " + velocity); // color: "+ wind_color);
mutable frame =dates[tick]+" - Wind direction: "+rotate+"° - Wind sector: "+direction + " - Wind speed: " + velocity;
mutable date_time = dates[tick];
mutable frame_angle = rotate;
mutable frame_direction = direction;
mutable frame_velocity = velocity;
mutable frame_wind_color = wind_color;
//*****************************************
// controllo del settore esterno del vento
sector.transition()
.attr("transform", " translate("+(xScale2(0)-(xScale2(0)-(w/2))/*+40*/)+", "+(yScale2(0)-(yScale2(0)-(h/2))/*+20*/)+") rotate(" + rotate + ")")
.attr("d", d3.arc()
.innerRadius( 15 )
.outerRadius( 1500 )
.startAngle (-Math.PI/12 ) // It's in radian, so Pi = 3.14 = bottom.
.endAngle( Math.PI/12 ) // 2*Pi = 6.28 = top
)
.attr('fill', wind_color)
.duration(animationSpeed/2)
//******************************************
//controllo del settore interno del vento
wind.transition()
.attr("transform", " translate("+(xScale2(0)-(xScale2(0)-(w/2))/*+40*/)+", "+(yScale2(0)-(yScale2(0)-(h/2))/*+20*/)+") rotate(" + rotate + ")")
.attr("d", d3.arc()
.innerRadius( 15 )
.outerRadius( 1500 )
.startAngle (-Math.PI/24 ) // It's in radian, so Pi = 3.14 = bottom.
.endAngle( Math.PI/24 ) // 2*Pi = 6.28 = top
)
.duration(animationSpeed/2)
//console.log(node)
//outerTick+=1;
//if(outerTick%15==0){
//if(b){
tick=tick+1 //incrementa l'indice principale
//}
//}
// riparte da capo quando ha spazzato l'array intero
if (tick >dates.length){
tick = 0
svg.selectAll(".rc").remove();
}
let daylyWindDir = rawWindDir
.filter(v=> v["DateTime"]===dates[tick] )
.map(v => ({DateTime: v.DateTime,
direction: v["direction"],
angle: v["angle"]
}))
rotate = daylyWindDir[0]["angle"]
rotateBlow = rotate;
direction = daylyWindDir[0]["direction"]
// console.log(rotateBlow)
//console.log(daylyWindDir[0]["angle"])
// get wind velocity
let daylyWindVel = rawWindVel
.filter(v=> v["DateTime"]===dates[tick] )
.map(v => ({DateTime: v.DateTime,
velocity: v["velocity"]
}))
velocity = daylyWindVel[0]["velocity"]
//**************************
// controllo della grandezza del blow. Si ricorda che scala linearmente da 0.33 a due in base alla velocità del vento
blowLength = blowLen(velocity);
//*****************************
//controllo del colore del vento. Sia del settore che delle frecce dei blow
var myColor = d3.scaleSequential().domain([min_wind_vel,max_wind_vel])
.interpolator(d3.interpolatePuRd);
wind_color = myColor(velocity)
// console.log(daylyWindDir[0]["angle"])
//***********************************
// Seleziona il Frame
// Filtra i dati relativi alla data indicata dal tick
let dayly2 = rawPerceptions
.filter(v=> v["DateTime"]==dates[tick] )
.map(v => ({name:v.recettore,
id: recettori.indexOf(v.recettore),
color:v.color
}))
//
//
//*************************************************
// Funzione per disegnare
dataset2
.nodes.forEach(function (n){
n['color'] = dayly2[dataset2.nodes.indexOf(n)].color
//console.log(n['color'])
//console.log(n['color'])
//date.attr("value", dates[tick]);
// if(n['name'] == "R 14"){
// if(n['color'] != "#000000"){ // secondo me va tolto
//console.log(n['color'])
var cn2 =n['name']
cn2 = cn2.replace(/ /g,"");
cn2 = "."+cn2;
svg.selectAll(cn2)
.attr("stroke", n['color'])
.attr("fill", n['color'])
// ***************************************
// Aggiunge i rettangoli per source detection
if(show_rects=='toggle'){
svg.selectAll(cn2)
.filter(v=>n['color']!="#000000" )
//.attr("stroke", n['color'])
//.attr("fill", n['color'])
.append("path")
.attr("class" ,"rc")
.attr("transform", " translate("+(xScale2(0)-(xScale2(0)-(w/2))/*+40*/)+", "+(yScale2(0)-(yScale2(0)-(h/2))/*+20*/)+") rotate(" + rotate + ")")
.attr("d", d3.arc()
.innerRadius( 15 )
.outerRadius( 1500 )
.startAngle (-Math.PI/24 ) // It's in radian, so Pi = 3.14 = bottom.
.endAngle( Math.PI/24 ) // 2*Pi = 6.28 = top
)
.style('stroke',"red")
.style('fill', "red")
.style("stroke-width",1)
.attr('opacity', 0.004)
.attr("transform", "rotate("+(rotate-180)+")")
}else{}
/*if(show_rects==true){
svg.selectAll(cn2)
.attr("stroke", n['color'])
.attr("fill", n['color'])
.append('rect')
.attr("class" ,"rc")
//.attr('x', n['x']-(xScale2(0)+40))
//.attr('y', n['y']-(yScale2(0)+20)-25)
.attr('x', -50)
.attr('y', 0)
//.attr('x', (xScale2(0) -(w/2) +40))
//.attr('y', (yScale2(0) -(w/2) +20))
.attr('width', 100)
.attr('height', 1000)
.style('stroke',"red")
.style('fill', "red")
.style("stroke-width",1)
.attr('opacity', 0.004)
.attr("transform", "rotate("+(180+rotate)+")")
}
else{
svg.selectAll(cn2)
.attr("stroke", n['color'])
.attr("fill", n['color'])
}*/
//*********************fine rettangoli
;
// } // if(n['color'] != "#000000"){
// } // if(n['name'] == "R 34"){
});
//svg.selectAll(".R40").attr("stroke", "red");
//console.log(tick)
}
return svg.node();
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Snap = require("https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg.js");
Insert cell
mapboxgl = {
const gl = await require("mapbox-gl@0.49");
if (!gl.accessToken) {
// This is @tmcw’s. https://www.mapbox.com/help/how-access-tokens-work/
//gl.accessToken = "pk.eyJ1IjoidG1jdyIsImEiOiJjamN0Z3ZiOXEwanZkMnh2dGFuemkzemE3In0.gibebYiJ5TEdXvwjpCY0jg";
gl.accessToken = "pk.eyJ1IjoiZ2VtbWVnIiwiYSI6ImNqemdtbHFlMTBnazUzbnBrMGl6Y2ozazIifQ.a39V4s3AOYKZElk56ydScg";
const href = await require.resolve("mapbox-gl@0.49/dist/mapbox-gl.css");
document.head.appendChild(html`<link href=${href} rel=stylesheet>`);
}
return gl;
}
Insert cell
html`<style> .markerz svg { width: 100%; height: 100%;}</style>`
Insert cell
html`<style> .marker{
pointer-events:none;
}</style>`
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