basic_map = function(data, style) {
const dimension = { height: style.height, width: width, margin: style.margin }
const svg_map = d3.create("svg")
.attr("viewBox", [0, 0, dimension.width, dimension.height]);
let p = d3.geoMercator()
.fitWidth(dimension.width - 4*dimension.margin, data.lines)
.center(d3.geoCentroid(map_data.lines))
.translate([dimension.width/2 - dimension.margin, dimension.height/2]);
let c = d => p([d.coordinates.lon, d.coordinates.lat]);
let radiusScale = d3.scaleSqrt()
.domain(d3.extent(data.points, d => d.size))
.range([style.point_radius_min, style.point_radius_max]);
svg_map.append("g")
.selectAll("path")
.data(data.lines.features)
.enter()
.append("path")
.attr("fill", style.map_fill)
.attr("stroke", style.map_stroke)
.attr("stroke-opacity", style.map_stroke_opacity)
.attr("stroke-width", style.map_stroke_width)
.attr("d", d3.geoPath().projection(p));
svg_map.append("g")
.selectAll("circle")
.data(data.points)
.enter()
.append("circle")
.attr("id", d => d.name)
.attr("cx", d => c(d)[0])
.attr("cy", d => c(d)[1])
.attr("r", d => radiusScale(d.size))
.attr("fill", style.point_fill)
.attr("fill-opacity", style.point_fill_opacity)
.attr("stroke", style.point_stroke)
.attr("stroke-width", style.point_stroke_width);
return svg_map.node();
}