-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Contour Smoothing Option: Dual Marching Squares #53
base: main
Are you sure you want to change the base?
Changes from all commits
4a2e9ff
07e58d3
1031d2c
fa89f82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"npm.packageManager": "yarn" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"version": "2.0.0", | ||
"tasks": [ | ||
{ | ||
"type": "npm", | ||
"script": "test", | ||
"group": { | ||
"kind": "build", | ||
"isDefault": true | ||
}, | ||
"problemMatcher": [], | ||
"label": "yarn: test", | ||
"detail": "tape 'test/**/*-test.js' && eslint src" | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -98,7 +98,62 @@ If *size* is specified, sets the expected size of the input *values* grid to the | |||||
|
||||||
<a name="contours_smooth" href="#contours_smooth">#</a> <i>contours</i>.<b>smooth</b>([<i>smooth</i>]) · [Source](https://github.com/d3/d3-contour/blob/master/src/contours.js), [Examples](https://observablehq.com/@d3/contours-smooth) | ||||||
|
||||||
If *smooth* is specified, sets whether or not the generated contour polygons are smoothed using linear interpolation. If *smooth* is not specified, returns the current smoothing flag, which defaults to true. | ||||||
If *smooth* is specified, sets the smoothing method to use when generating the contour polygons. If *smooth* is not specified, returns the current smoothing method, which defaults to true. | ||||||
|
||||||
The available *smooth* options are: | ||||||
|
||||||
- `false`: Smoothing is disabled. | ||||||
- `true` or `"linear"` (Default): Linear interpolation smoothing, as described in the original [Marching Squares algorithm](https://en.wikipedia.org/wiki/Marching_squares). | ||||||
- `"linearDual"`: Dual linear interpolation smoothing, as described in the [Dual Marching Squares algorithm](https://ieeexplore.ieee.org/document/7459173). | ||||||
|
||||||
In general, the quality of each smoothing method is inversely proportional to its runtime performance. | ||||||
|
||||||
Additionally, the density of the source data impacts contour smoothness: the differences between the smoothing methods are more noticeable with low-density data than they are with high-density data. With _very_ high-density data, there is no discernible quality difference between the three methods. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
<table> | ||||||
<thead> | ||||||
<tr> | ||||||
<th colspan="2" scope="colgroup"></th> | ||||||
<th colspan="2" scope="colgroup" style="text-align: center;">Low-density data</th> | ||||||
<th colspan="2" scope="colgroup" style="text-align: center;">High-density data</th> | ||||||
</tr> | ||||||
<tr> | ||||||
<th colspan="2" scope="col">Smoothing method</th> | ||||||
<th scope="col" style="text-align: center;">Contour<br/>quality</th> | ||||||
<th scope="col" style="text-align: center;">Performance<br/>cost*</th> | ||||||
<th scope="col" style="text-align: center;">Contour<br/>quality</th> | ||||||
<th scope="col" style="text-align: center;">Performance<br/>cost*</th> | ||||||
</tr> | ||||||
</thead> | ||||||
<tbody> | ||||||
<tr> | ||||||
<th scope="row">None</th> | ||||||
<th scope="row"><code>false</code></th> | ||||||
<td>Poor</td> | ||||||
<td>+0%</td> | ||||||
<td>Good</td> | ||||||
<td>+0%</td> | ||||||
</tr> | ||||||
<tr> | ||||||
<th scope="row">Linear (Default)</th> | ||||||
<th scope="row"><code>true</code> or<br /><code>"linear"</code></th> | ||||||
<td>Good</td> | ||||||
<td>+2.40%</td> | ||||||
<td>Best</td> | ||||||
<td>+1.55%</td> | ||||||
</tr> | ||||||
<tr> | ||||||
<th scope="row">Dual linear</th> | ||||||
<th scope="row"><code>"linearDual"</code></th> | ||||||
<td>Best</td> | ||||||
<td>+2.70%</td> | ||||||
<td>Best</td> | ||||||
<td>+2.00%</td> | ||||||
</tr> | ||||||
</tbody> | ||||||
</table> | ||||||
|
||||||
\* Estimated performance cost based on 2 sample datasets. | ||||||
Comment on lines
+112
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove (this is interesting in the PR but too overwhelming for the README) |
||||||
|
||||||
<a name="contours_thresholds" href="#contours_thresholds">#</a> <i>contours</i>.<b>thresholds</b>([<i>thresholds</i>]) · [Source](https://github.com/d3/d3-contour/blob/master/src/contours.js), [Examples](https://observablehq.com/@d3/volcano-contours) | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -182,6 +182,39 @@ export default function() { | |||||
}); | ||||||
} | ||||||
|
||||||
/** | ||||||
* Applies smoothing to an iso-ring according to the Dual Marching Squares algorithm. | ||||||
* @param {[number, number][]} ring The sorted list of (x,y) coordinates of points for a given iso-ring. | ||||||
* @param {number[]} values The underlying grid values. | ||||||
* @param {number} value The iso-value for this iso-ring. | ||||||
*/ | ||||||
function smoothLinearDual(ring, values, value) { | ||||||
var point, x, y, x1, y1; | ||||||
|
||||||
// The first step in Dual Marching Squares smoothing is linear interpolation. | ||||||
smoothLinear(ring, values, value); | ||||||
|
||||||
for (var i = 0; i < ring.length; i++) { | ||||||
point = ring[i]; | ||||||
x = point[0]; | ||||||
y = point[1]; | ||||||
|
||||||
if (i < ring.length - 1) { | ||||||
// Next point | ||||||
x1 = ring[i + 1][0]; | ||||||
y1 = ring[i + 1][1]; | ||||||
|
||||||
// Set the current point to the midpoint between it and the next point. | ||||||
point[0] = x + (x1 - x) / 2; | ||||||
point[1] = y + (y1 - y) / 2; | ||||||
} else { | ||||||
// This is the last point, complete the ring by matching the first point | ||||||
point[0] = ring[0][0]; | ||||||
point[1] = ring[0][1]; | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
contours.contour = contour; | ||||||
|
||||||
contours.size = function(_) { | ||||||
|
@@ -196,7 +229,7 @@ export default function() { | |||||
}; | ||||||
|
||||||
contours.smooth = function(_) { | ||||||
return arguments.length ? (smooth = _ ? smoothLinear : noop, contours) : smooth === smoothLinear; | ||||||
return arguments.length ? (smooth = _ === 'linearDual' ? smoothLinearDual : _ ? smoothLinear : noop, contours) : smooth === smoothLinear || smooth === smoothLinearDual; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
}; | ||||||
|
||||||
return contours; | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.