D3:隐藏下降的voronoi笔画'in the sea'
D3: hide voronoi strokes that fall 'in the sea'
隐藏掉落在海中的所有 voronoi 笔划的最少 'expensive' 方法是什么?
陆地上 运行 的笔触(和多边形填充)应该可见,而海上的笔触应该隐藏起来。我想我的objective从下图应该就清楚了:
我能想到两个方案:
- 不知何故 'reclip' voronoi 多边形到基础国家
('land') 个多边形。这听起来超级 CPU 密集。这不是一个
不错的选择,那我们还是别去了。
- 在 voronoi 镶嵌上叠加一个 'sea' 多边形。那
在视觉上会非常有效,而且正是我所需要的。我将如何根据国家底图计算新的海洋多边形? (例如这个
jsfiddle with a geoJSON D3 map) 我有多张多边形复杂程度各不相同的地图,因此我需要一种万无一失的方法来构建该地图。
任何ideas
?
一个简单的选项,需要 none 个:
- 海洋多边形
- 重绘陆地多边形/合并陆地多边形
- 剪辑路径
是使用svg图案。这听起来可能有点奇怪,而且我对性能影响并不乐观,但是可以使用您的 voronoi 图的模式来填充您的 countries/features(保留边界并允许一次绘制特征只有一次)。
这要求多边形填充不依赖于地理特征而是依赖于 voronoi - 您的图像对每个多边形使用相同的填充,但您的问题文本可能暗示情况并非如此
要使用这样的图案,请创建一个与您的地图宽度和高度相同的图案。在模式中,放置 voronoi 图路径。最后,将每个特征的填充设置为模式:
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var projection = d3.geoMercator()
.scale((width - 3) / (2 * Math.PI))
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
var graticule = d3.geoGraticule();
d3.json("https://unpkg.com/world-atlas@1/world/50m.json", function(error, world) {
if (error) throw error;
// random points:
var circles = d3.range(20).map(function() {
return {
x: Math.round(Math.random() * width),
y: Math.round(Math.random() * height)
};
});
// voronoi:
var voronoi = d3.voronoi()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.extent([[-1, -1], [width + 1, height + 1]]);
// pattern:
var pattern = svg.append("defs")
.append("pattern")
.attr("id","voronoi")
.attr("patternUnits","userSpaceOnUse")
.attr("width", width)
.attr("height",height)
.attr("x",0)
.attr("y",0)
pattern.selectAll("path")
.data(voronoi.polygons(circles))
.enter()
.append("path")
.attr("d", renderCell)
.attr("fill",function(d,i) { return d3.schemeCategory20[i]; })
// append paths as normal:
var features = svg.selectAll(null)
.data(topojson.feature(world,world.objects.countries).features)
.enter()
.append("path")
.attr("class", "boundary")
.attr("d", path)
.attr("fill","url(#voronoi)"); // fill with pattern
function renderCell(d) {
return d == null ? null : "M" + d.join("L") + "Z";
}
});
.boundary {
stroke: black;
stroke-width: 1px;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<svg width="600" height="400"></svg>
隐藏掉落在海中的所有 voronoi 笔划的最少 'expensive' 方法是什么?
陆地上 运行 的笔触(和多边形填充)应该可见,而海上的笔触应该隐藏起来。我想我的objective从下图应该就清楚了:
我能想到两个方案:
- 不知何故 'reclip' voronoi 多边形到基础国家 ('land') 个多边形。这听起来超级 CPU 密集。这不是一个 不错的选择,那我们还是别去了。
- 在 voronoi 镶嵌上叠加一个 'sea' 多边形。那 在视觉上会非常有效,而且正是我所需要的。我将如何根据国家底图计算新的海洋多边形? (例如这个 jsfiddle with a geoJSON D3 map) 我有多张多边形复杂程度各不相同的地图,因此我需要一种万无一失的方法来构建该地图。
任何ideas
?
一个简单的选项,需要 none 个:
- 海洋多边形
- 重绘陆地多边形/合并陆地多边形
- 剪辑路径
是使用svg图案。这听起来可能有点奇怪,而且我对性能影响并不乐观,但是可以使用您的 voronoi 图的模式来填充您的 countries/features(保留边界并允许一次绘制特征只有一次)。
这要求多边形填充不依赖于地理特征而是依赖于 voronoi - 您的图像对每个多边形使用相同的填充,但您的问题文本可能暗示情况并非如此
要使用这样的图案,请创建一个与您的地图宽度和高度相同的图案。在模式中,放置 voronoi 图路径。最后,将每个特征的填充设置为模式:
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var projection = d3.geoMercator()
.scale((width - 3) / (2 * Math.PI))
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
var graticule = d3.geoGraticule();
d3.json("https://unpkg.com/world-atlas@1/world/50m.json", function(error, world) {
if (error) throw error;
// random points:
var circles = d3.range(20).map(function() {
return {
x: Math.round(Math.random() * width),
y: Math.round(Math.random() * height)
};
});
// voronoi:
var voronoi = d3.voronoi()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.extent([[-1, -1], [width + 1, height + 1]]);
// pattern:
var pattern = svg.append("defs")
.append("pattern")
.attr("id","voronoi")
.attr("patternUnits","userSpaceOnUse")
.attr("width", width)
.attr("height",height)
.attr("x",0)
.attr("y",0)
pattern.selectAll("path")
.data(voronoi.polygons(circles))
.enter()
.append("path")
.attr("d", renderCell)
.attr("fill",function(d,i) { return d3.schemeCategory20[i]; })
// append paths as normal:
var features = svg.selectAll(null)
.data(topojson.feature(world,world.objects.countries).features)
.enter()
.append("path")
.attr("class", "boundary")
.attr("d", path)
.attr("fill","url(#voronoi)"); // fill with pattern
function renderCell(d) {
return d == null ? null : "M" + d.join("L") + "Z";
}
});
.boundary {
stroke: black;
stroke-width: 1px;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<svg width="600" height="400"></svg>