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

Fix decimate deleting end of a freedrawing line #6966

Merged
merged 3 commits into from
May 16, 2021

Conversation

BinaryMoon
Copy link
Contributor

Stop decimate from deleting the last point on the line, whilst ensuring the line is always > 1 point in length (so that it actually displays)

Fixes this ticket: #6951

Stop decimate from deleting the last point on the line, whilst ensuring the line is always > 1 point in length (so that it actually displays)

fabricjs#6951
@asturur
Copy link
Member

asturur commented Mar 30, 2021

this could work, but can you check what happens for single click points with drawing brush? We should still get a circle.

if (newPoints.length === 1) {
newPoints.push(new fabric.Point(newPoints[0].x, newPoints[0].y));
}
/**
Copy link
Member

Choose a reason for hiding this comment

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

or couldn't we just check in the loop

if (cDistance >= adjustedDistance || i === l - 1) {

?

Copy link
Member

Choose a reason for hiding this comment

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

Because with your solution we risk to duplicate the last point in case is already there? or am i reading something wrong?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is also an option. I liked the simplicity of my solution, which actually removed code, but I can see that it may sometimes duplicate the last point. I shall have another think and try some other options.

@BinaryMoon
Copy link
Contributor Author

this could work, but can you check what happens for single click points with drawing brush? We should still get a circle.

Yes - a single click still works. Previously (the code I removed) added the last point again. Since there was only one point point[0] is the last point. Essentially all this code does is remove the check for line length and always add the last point to the end. In my tests it worked well on a variety of drawing speeds, just clicking, and different decimate amounts.

Don't double add the last point
@@ -246,16 +246,18 @@
var zoom = this.canvas.getZoom(), adjustedDistance = Math.pow(distance / zoom, 2),
i, l = points.length - 1, lastPoint = points[0], newPoints = [lastPoint],
cDistance;
for (i = 1; i < l; i++) {
for (i = 1; i < l - 1; i++) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went a slightly different way to your suggestion and changed the loop to ignore the last point, and then always add it at the end.

With this method the line will always be at least 2 points long, because newPoint has the first point added when it's initialized, and the last point added after the decimation. The decimation then only happens to the points in the middle of the line.

This removes the need to check the line length, and reduces the amount of checks made when decimating the line.

Admittedly very small improvements but I like it :)

I have tested this with single clicks and long lines.

If you're not happy with this I'd be happy to use your suggestion. I don't mind what the solution is as long as it works. :)

Copy link
Member

Choose a reason for hiding this comment

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

this looks good to me.
Way better than my try.
Now the last step. Can we write a test that will fail if this commit is removed?

Let me see if i can find a semi ready test

Copy link
Member

Choose a reason for hiding this comment

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

no we haven't, so i started one

        QUnit.test('decimate points', function(assert) {
          var brush = new fabric.PencilBrush(canvas);
          var points = [{ x: 1, y: 0 }, { x: 2, y: 0 }, { x: 3, y: 0 }, { x: 4, y: 0 }, { x: 5, y: 0 }];
          var distance = 6;
          var newPoints = brush.decimatePoints(points, distance);
          assert.equal(newPoints[0], points[0], 'first point is always present');
          // add more conditions... or more tests.
        });

this test would go at the end of last test in this file:

test/unit/brushes.js

and provided you npm installed fabric locally, you can execute the tests runing:

npm run test:single test/unit/brushes.js

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was able to run the test. That's great. Thanks!

I've never done any JavaScript testing before.

Copy link
Member

Choose a reason for hiding this comment

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

Please add a test so we merge the PR.
What is important to cover in the test is your change.
So give a list of points in which the last point is distat from the previous once less than distance, it should be still available in the output.

Any PR to any public repo should generally, as a rule of thumb, ask you for tests.
Is too much easy to forget features and delete previous fixes with changes otherwise.
And our coverage is not even perfect.

@asturur
Copy link
Member

asturur commented Apr 11, 2021

@BinaryMoon can you add a test for this change? so we can merge the pr

@stale
Copy link

stale bot commented Apr 26, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale Issue marked as stale by the stale bot label Apr 26, 2021
@BinaryMoon
Copy link
Contributor Author

Hi there - Sorry for the very delayed reply. Work and real life got in the way.

I'd really like to work on this and add a test but I have no idea what I'm doing. I've never written a unit test and I don't know how to generate the data.

Sorry :(

@stale stale bot removed the stale Issue marked as stale by the stale bot label Apr 26, 2021
@asturur
Copy link
Member

asturur commented Apr 27, 2021

No worries @BinaryMoon this is a free open project and people dedicate the time they can.
I'll guide you to write a test, is very important for open software to have tests, and i want your contrbution to come with one.
When is ready, is ready.

@BinaryMoon
Copy link
Contributor Author

Hi - thanks for your understanding! :)

I had some time to go through this today and it was easier than I thought it would be. I've added the test you mentioned and added a couple of additional tests.

Hopefully that works ok.

@BinaryMoon
Copy link
Contributor Author

Also - do you have any coding standards to follow? The formatting standards I use for work are very different to what I can see here so it makes it harder to edit things without reformatting the entire file. I've been working out the changes locally then applying the changes on Github directly - but that's not the niceset workflow :)

@asturur
Copy link
Member

asturur commented May 16, 2021

Hi @BinaryMoon sorry for not answering, i moved fabricJS emails out of my inbox and i m still getting adjusted to it.
In the repo you find a lint command and a lint command for tests.
If you run npm run lint or npm run lint_tests you get the check for the only code standards that are catched as regressions.
Other than that we still use ES5, so that is the other coding standard you have to follow.
We still keep ie11 working with no transpiler ( i think this is the last version that does it )

@asturur
Copy link
Member

asturur commented May 16, 2021

In theory your IDE should pick up the eslint file from the project and adjust itslef to respect the rules.
What ide do you use?

@asturur asturur merged commit 77ca575 into fabricjs:master May 16, 2021
@BinaryMoon
Copy link
Contributor Author

Thanks for merging this! :)

I have been using Atom to edit this. When I saved the file(s) it reformatted the same thing. I don't know if that's because of an extension or something else but I suspect that's not what you want.

I'll see if I can work out how to get the eslint file to be recognised.

@asturur asturur mentioned this pull request May 22, 2021
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.

2 participants