Skip to content

curve: "auto" (line + projection) #1156

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

Merged
merged 5 commits into from
Dec 6, 2022
Merged

Conversation

Fil
Copy link
Contributor

@Fil Fil commented Dec 5, 2022

closes #1146

beagle

@Fil Fil added enhancement New feature or request geo Maps and projections labels Dec 5, 2022
@Fil Fil requested a review from mbostock December 5, 2022 13:32
@Fil Fil force-pushed the fil/line-interpolate-geodesic branch from 0b99d4e to da061c1 Compare December 5, 2022 13:52
Copy link
Member

@mbostock mbostock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid creating an entirely new Mark class for this. Basically, I would check whether the curve is "geodesic" in the constructor, and if so, don’t bind the x and y channels to their respective scales. Then use the projection and geoPath instead of the line shape during render.

In addition to being less code, this should be more maintainable; less likely that the two implementations could drift. And of course you could test instanceof Line and you’d get the expected result. (It’s highly surprising if calling Plot.line doesn’t return an instance of Plot.Line.)

I think I would also prefer the simpler name "sphere". I know that "geodesic" is the mathematically-precise term, but wouldn’t "sphere" be easier to remember? And I don’t think we’ll have multiple forms of spherical interpolation.

@Fil Fil changed the title curve: "geodesic" curve: "sphere" Dec 5, 2022
@Fil Fil requested a review from mbostock December 5, 2022 20:52

// When the line mark is used with a "sphere" curve and a projection
// (supposedly spherical), keep x and y as numbers.
const sphere = curve === "sphere";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You’ll need to coerce curve to a string and toLowerCase etc.

path({
type: "LineString",
coordinates: Array.from(I, (i) => [+X[i], +Y[i]]).filter(([x, y]) => !isNaN(x + y))
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do this faster by invoking the projection stream directly (calling stream.lineStart, stream.point, stream.lineEnd) rather than going through geoPath.

Also, this will coerce nulls to zero rather than skipping them. We might want to use coerceNumbers here, but we should at least be consistent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

groupIndex already does filtering for undefined values, so we can check if i is -1 here instead. I’ll push some commits.

@mbostock mbostock force-pushed the fil/line-interpolate-geodesic branch from 15a7425 to 12bb0f1 Compare December 6, 2022 02:23
@mbostock
Copy link
Member

mbostock commented Dec 6, 2022

I reverted fc75219 since that seems unrelated (and there are no tests so I’m not sure what it was trying to fix).

I’ve also renamed it to curve "projection" since there’s no logic here that’s specific to spheres and the projection isn’t even required.

@mbostock mbostock changed the title curve: "sphere" curve: "projection" Dec 6, 2022
@mbostock mbostock merged commit d70fd8b into main Dec 6, 2022
@mbostock mbostock deleted the fil/line-interpolate-geodesic branch December 6, 2022 02:25
@Fil
Copy link
Contributor Author

Fil commented Dec 6, 2022

The use case for fc75219 were the x/y coordinates passed as strings in the beagle.js example. Now solved by coerceNumbers in sphereLine.

@Fil Fil changed the title curve: "projection" curve: "projection" (now: "projected") Dec 7, 2022
Comment on lines +44 to +45
x: {value: x, scale: curve === curveProjection ? undefined : "x"}, // unscaled if projected
y: {value: y, scale: curve === curveProjection ? undefined : "y"}, // unscaled if projected
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #1165

@Fil Fil changed the title curve: "projection" (now: "projected") curve: "auto" (line + projection) Dec 8, 2022
@Fil Fil mentioned this pull request Dec 8, 2022
chaichontat pushed a commit to chaichontat/plot that referenced this pull request Jan 14, 2024
* curve: "geodesic" for Plot.line

closes observablehq#1146

* Line handles the "sphere" curve to follow great circles on spherical projections.

* fix filtering, input normalization

* Update README

* curve: "projection"

Co-authored-by: Mike Bostock <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request geo Maps and projections
Projects
None yet
Development

Successfully merging this pull request may close these issues.

variable color for geo lines?
2 participants