平滑 D3.js/GeoJSON/TopoJSON/Shapefile 中的弧线/绘图点(沿途某处)
Posted
技术标签:
【中文标题】平滑 D3.js/GeoJSON/TopoJSON/Shapefile 中的弧线/绘图点(沿途某处)【英文标题】:Smoothing arcs/plot points in D3.js/GeoJSON/TopoJSON/Shapefile (somewhere along the way) 【发布时间】:2015-06-06 04:41:59 【问题描述】:我一直在寻找这个问题的答案,但我一直无法弄清楚。
我最终要从基于网格的数据(GRIB 文件)创建一个 TopoJSON 文件。 我可以很容易地将数据插入到分辨率更高的网格中,这样在缩小时绘图点显得更平滑,但在放大时,不可避免地会看到块状网格点。 我还研究了简化,这确实有助于有点,但它不是很平滑。 我正在使用 D3 来呈现数据。 这是可以在前端完成的事情,还是应该/可以在原始 TopoJSON 数据中完成? 我基本上不希望您能够分辨出它是一个网格,即使您将其放大 10,000%。 以下是我所追求的示例:【问题讨论】:
相关Making a SVG path like a smooth line instead of being ragged 任何时候您需要在所有分辨率下连续平滑线条,您的选择基本上归结为大文件或 SVG。我希望解决方案是采用简化的数据并将其转换为 SVG,并在角上进行四舍五入以达到预期的效果。 另外,作为一名土木工程师,我首先会问为什么需要这样做 - 它意味着您的数据集中不存在的准确性水平,对于我处理的大多数问题,夸大你的准确性是一个严重的责任问题。根据您的使用情况,如果这样做可能会误导用户并导致错误的结论,那么这样做可能是不好的做法。我个人更喜欢显示(例如)块状的东西来直观地表示“+/- 5 英尺”,而不是可能落在物业角落错误一侧的完美的 0 宽度线。 @brichins 完全理解您的担忧,但这是一个气象问题。从历史上看,数据点的平均值(以及插值算法)创建了漂亮的平滑图(ArcGIS、qGIS、GrADS)——这对于这个应用程序来说是最消耗的。天气数据的分辨率一般不是很高(GFS 刚刚升级到 0.25 度)。 This question 可能会有所帮助。 【参考方案1】:也许d3 line.interpolate() 是您要找的?
更多信息: http://www.d3noob.org/2013/01/smoothing-out-lines-in-d3js.html
【讨论】:
这是为了平滑线而不是路径。【参考方案2】:如果您使用的是 D3.js,并且您正在使用线条,那么内置的 interpolate() 函数就是最佳选择。
这是 D3 的 line.interpolate() 使用“基数”平滑的工作示例:
http://codepen.io/gracefulcode/pen/doPmOK
代码如下:
var margin =
top: 30,
right: 20,
bottom: 30,
left: 50
,
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.interpolate("cardinal")
.x(function(d)
return x(d.date);
)
.y(function(d)
return y(d.close);
);
// Adds the svg canvas
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Get the data
d3.json('https://api.myjson.com/bins/175jl', function(error, data)
data.forEach(function(d)
d.date = parseDate(d.date);
d.close = +d.close;
);
// Scale the range of the data
// Starting with a basic graph 14
x.domain(d3.extent(data, function(d)
return d.date;
));
y.domain([0, d3.max(data, function(d)
return d.close;
)]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
);
【讨论】:
谢谢,但 topojson 会附加路径,而不是行。不幸的是,标准插值/平滑不起作用。【参考方案3】:这是可以在前端完成的事情,还是应该/可以在原始 TopoJSON 数据中完成?
这是应该在前端完成的事情。如果您在将数据写入 JSON 文件之前对其进行平滑处理,那么该文件将不必要地大。
【讨论】:
我接受这个,因为这基本上是我发现的。算法需要在前端执行此操作,否则文件大小会非常大。使用 D3/topojson,目前没有内置功能可以正确执行此操作。必须手卷。 另外,当在前端完成插值时,可以延迟执行——如果用户不放大,则不需要执行插值。 还可能值得指出一个明显的声明:GeoJSON/Topojson 不支持贝塞尔曲线。这种格式的平滑曲线实际上是由许多许多直线组成的曲线。因此,如果您决定将其烘焙到原始数据中,则文件大小会更大。以上是关于平滑 D3.js/GeoJSON/TopoJSON/Shapefile 中的弧线/绘图点(沿途某处)的主要内容,如果未能解决你的问题,请参考以下文章
shader编程-三维场景下SDF建模,平滑交集平滑并集平滑差集(WebGL-Shader开发基础11)
shader编程-三维场景下SDF建模,平滑交集平滑并集平滑差集(WebGL-Shader开发基础11)
shader编程-三维场景下SDF建模,平滑交集平滑并集平滑差集(WebGL-Shader开发基础11)