Skip to content
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

split the input polyline into multiple polylines when there is Nan/Nu… #49

Merged
merged 9 commits into from
Dec 26, 2020

Conversation

ruijin
Copy link
Contributor

@ruijin ruijin commented Dec 18, 2020

…ll in the input. plotly need this behavior to correctly render scatter chart.

related to this plotly issue:
plotly/plotly.js#2291 (comment)

…ll in the input. plotly need this behavior to correctly render scatter chart.
index.js Outdated
if(!(state.count-1 in ids))
ids[state.count] = state.count-1 // make sure there is at least polygon

let splits = Object.keys(ids).map(e => e|0).sort(function(a, b){return a - b})
Copy link
Member

@dy dy Dec 19, 2020

Choose a reason for hiding this comment

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

What's the purpose of map(e => e|0)? Cast to number? Better .map(Number).
Why does sort need that default comparator?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the lambda is for casting, will replace it with map(Number)
The comparator for sort is to sort by number value rather than string order.

Sorry I am not very fluent in javascript.

Copy link
Member

@dy dy left a comment

Choose a reason for hiding this comment

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

Please provide test case in test.js.

index.js Outdated

for (let i = 0; i < splits.length; i++)
{
let triangles = triangulate(pos.slice(base*2, splits[i]*2), state.hole || [])
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure I follow the logic here, but placing triangulate in a loop looks suspicious.
Could you please elaborate a bit what algorithmic changes are done here?

Copy link
Contributor Author

@ruijin ruijin Dec 19, 2020

Choose a reason for hiding this comment

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

The issue is when plotly send scatter segment to regl (which is seperated by null in plotly input), plotly close each segment and drop the nulls. When regl receive the segments, regl treat it as a single big plygon which end up drawing some extra triangles.

I submitted a PR (plotly/plotly.js#5355) to plotly to keep those nulls. However that itself is not enough since regl will replace the null with last valid point and still send a single polygon for triangulation. I don't see earcut.js supporting multiple polygon in a single input yet. So the proposed solution here is to call triangulation multiple time, each time only handle one segment (polygon).

@ruijin
Copy link
Contributor Author

ruijin commented Dec 19, 2020

New submit add tests. It also handles holes now. The idea is for each polygon we create a new temporary position buffer that contains a single polygon and all the wholes (earcut.js support multiple holes). And when the vertex index comes back from earcut.js we map it back to the original position buffer.

Below are test output before and after the fix.

Before:
regl_pre_fix

After:
regl_post_fix

make the index mapping of temporary clearer

Co-authored-by: Mojtaba Samimi <[email protected]>
@ruijin ruijin requested review from dy and archmoj December 22, 2020 02:40
@ruijin
Copy link
Contributor Author

ruijin commented Dec 23, 2020

regl-line2d/index.js

Lines 446 to 458 in e7ff2a4

if (o.thickness != null) state.thickness = parseFloat(o.thickness)
if (o.opacity != null) state.opacity = parseFloat(o.opacity)
if (o.miterLimit != null) state.miterLimit = parseFloat(o.miterLimit)
if (o.overlay != null) {
state.overlay = !!o.overlay
if (i < Line2D.maxLines) {
state.depth = 2 * (Line2D.maxLines - 1 - i % Line2D.maxLines) / Line2D.maxLines - 1.;
}
}
if (o.join != null) state.join = o.join
if (o.hole != null) state.hole = o.hole
if (o.fill != null) state.fill = !o.fill ? null : rgba(o.fill, 'uint8')
if (o.viewport != null) state.viewport = parseRect(o.viewport)

Why here we store the input option to state? And is it true that when some field is missing in the input option, the stored value in state will be used instead? I ran into a issue during debugging notice that a path could pick up the "hole" of another path, which cause error. I don't know enough about this part of code so I did not touch it. But is this a bug?

@dy
Copy link
Member

dy commented Dec 23, 2020

Why here we store the input option to state? And is it true that when some field is missing in the input option, the stored value in state will be used instead?

There can be multiple passes, ie. multiple lines to render, and each can have its own properties (like fill, opacity etc.), so we form state objects - each per render pass (=per shape to render). Props can be updated, yes, and not necessary all - only some props can get new value.

@ruijin ruijin requested a review from dy December 24, 2020 04:31
Copy link
Member

@dy dy left a comment

Choose a reason for hiding this comment

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

These tests introduce WebGL warning
image
probably some attribute/vertex is off, worth figuring out

@ruijin
Copy link
Contributor Author

ruijin commented Dec 25, 2020

when setting stroke to null, line2d will still trying to render miter join while the stroke vertex are not there. Using thickness = 0 solve (or get around) this. Not sure if this behavior is desired or not. But since it's not related to the issue of this PR, I will leave it there.

@ruijin ruijin requested a review from dy December 25, 2020 01:26
Copy link
Member

@dy dy left a comment

Choose a reason for hiding this comment

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

LGTM

@archmoj archmoj merged commit dec9c08 into gl-vis:master Dec 26, 2020
@archmoj
Copy link
Contributor

archmoj commented Dec 26, 2020

Published [email protected] minor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants