Open alexeevilya opened 9 years ago
Another artifact:
I think it has the same cause.
Yeah, setting the thickness to a large value ( you dont have to scale the stroke to make it appear) can make the joints degenerate. It is an unfortunate side effect of the math code. The rectangles that are created to draw the lines become overlapped and it looks very bad.
You can try to solve the same problem by drawing 2 quadrilaterals on a piece of paper to fit every type of joint in every angle. It rapidly becomes very hard to make the joint look good without overdraw or disfigured shapes as a result :)
Ion, thanx, but are you sure that nothing can be done? (until a certain scale, everything looks great). For my app it is a catastrophic problem (
What is the actual problem you are trying to solve?
Is it the scaling? Or is it when you need to draw lines with many control points?
If it is the scaling, you can do the scaling math on the vertices of the Stroke yourself, before you add them as vertices to the Stroke, and keep the thickness constant (and small) so the artifacts aren't as visible.
In the second example, what is the goal there? If you wish to draw smooth curves, check out the ShapeEx.graphics.NaturalCubicSplineTo method
Well, I have to agree that I do find something odd that goes beyond what should be expected when the line turns on itself with large thickness... There is definitely something wrong. I will try to look into it, even though I doubt I will find the bug tonight.
Could you please test with the following additional code:
if ( elbowThickness > d0 )
elbowThickness = d0;
if ( elbowThickness > d1 )
elbowThickness = d1;
Add that to the Stroke class, around line 353, as the last four lines in the "if ( treatAsRegular )" statement.
I know this is probably cumbersome for you to test, but I would like to see the effect of this on the problems you are seeing. I don't want to submit it as a fix, but it seems to make some of my test cases look better (if not perfect)
Just let me know what happens, ok?
Ion, Thank you very much for your care and help to solve this problem! Unfortunately, that kills one problem, but born another. There's a new artifact:
In the real application, it looks like this,
before:
after:
Ah, ok. Can I ask you how many points you have per stroke in your "real" application? It looks like a program to map sailing boats, perhaps?
The original problem occurs when the thickness of a joint gets thicker than the distance of the line segments, and the fix tried to correct that. It seems to me that you have a very large amount of data points in your "real" application, making each line segment between two vertices pretty small compared to the thickness?
IF that is the case, the thickness will rapidly get thicker than each line segment, and what I would do in that case would be to "clean" the input data, removing points that are (more or less) on the same line, or points that create "dents" in the line.
If you try this instead: if ( elbowThickness > d0 ) elbowThickness = vThickness; if ( elbowThickness > d1 ) elbowThickness = vThickness;
could you let me know the difference?
Ion, yes, it is a sailing boats map application. As for the number of vertices, then I use simplify algorithm, and there is a one vertex for the one really map point after simplifying. Sorry for my English, one moment ... ;)
Don't worry about your English, I understand you fine. I am sorry I can't help you very well.
Thank you, now I'm testing the new changes by you.
Oh my God! ;)
By the way, my other sandbox to test an application is project, that reference is attached above. https://www.dropbox.com/s/om7v84i2iibpp53/pathTest.zip?dl=0
The lines get very thin in some places, but the bad joints look better.. Hmmm..
Please, look at the dropbox example...
I am away from my Flash dev environment today, so I cant test any code. Sorry.
Oh, no problem. But as you can see, the line in dropbox example is very thin, although there is only four vertexes in that.
Please, look at this example - https://www.dropbox.com/s/wr1cu8ynz2axioa/PathTest.swf?dl=0 You need to scroll by the wheel.
In short, the problem occurs when the thickness of a joint gets thicker than the distance of the line segments. Unfortunately, the fix does not correct that problem.
Yeah, I figured it doesnt solve it. And I wrote that earlier: "The original problem occurs when the thickness of a joint gets thicker than the distance of the line segments" :) Unfortunately, I can't do any work on this for a few days (Going to Berlin for the Quo Vadis game conference)
All clear. However, I will be very grateful to you, Ion, if you can find time to fix the problem after coming back.
I will try. In the mean while, if you wish to try something different, you can check out the FastStroke class. It doesnt make such nice joints between line segments, as it just creates rectangles for the lines, but it might help you if the joints look too bad. It should work very similar to the Stroke class.
However, it is much less used and might not work very well. It was one of my experiments at one point
Also, of course, that will not support the "postProcess" method
Thank you, Ion! That looks nice, but:
..and what capacity is?Is it the number of lineTo()/moveTo() calls? Or lineTo() calls * 2?
Number one is fixed by change line 307 at FastStroke class:
RenderSupport.setBlendFactors(_material.premultipliedAlpha, this.blendMode == BlendMode.AUTO ? renderSupport.blendMode : this.blendMode);
but fps is bad (the fan on my laptop is working like crazy now)
Ok, thank you for trying that out at least.
Hmmm.. Maybe I'm doing something wrong again? If you call it fast, then is it probably really fast? ;)
I was hoping it would be faster in certain scenarios but it turned out it wasn't a whole lot better than the regular Stroke, except for some very specific cases. As I said, it was an experiment. Thanks for trying it out.
Don"t mention it! Thank YOU! By the way, I found comparison of FastStroke, Stroke and 'StrokeGraphics' in #92 thread. What 'StrokeGraphics' is? Should I try it?
The "StrokeGraphics" mentioned is the Stroke you get when using the Shape.graphics API
So, no, it's not a separate class.
Hi Ion! Have you any news about our problem? Do you try to fix that?
No, sorry, I have no new ideas for a solution to this problem, except making a dynamic cleaning of the in-data points depending on the zoom value. When the view covers a large area of the map, fewer points should be needed in order to present a good line, and it should be possible to clean them up a bit in those scenarios
Thank you, IonSwitz! Yea, dynamic cleaning of the in-data points is a way to fix the problem and many cartografical tools uses simplification algorithms for that, but its reduce the performance itself (especially if uses in every frame actions such as follow-zoom animation) ;(
I have submitted some new code that will help you when scaling a Stroke.
when you scale the stroke, do this to maintain screen-relative stroke thickness:
this.scale = scaleValue; stroke.scaleGeometry( scaleValue); // new method on Stroke class
Note: Combining this with adding new points to the Stroke during the same frame is a bit nasty, and should be avoided. If you generate your full Stroke once, and then just use this for scaling, it should work fine, and be relatively fast. Currently, it's probably a good idea to set the "scaleGeometry" to 1.0 before calling "lineTo" on the Stroke.
So, instead of having to re-add all stroke points ( "lineTo" ) to the Stroke when scaling, you can just do this extra call. It should be a lot faster than re-adding all stroke points, but it is still some math that has to be done. Please try it, if you are still using this functionality.
Also, I have added some fixes that improves the quality of drawing thick lines, so your sharp turns should look a lot better.
Also, as an experiment, I have added a method on Stroke allowing a "cullDistance". Basically, when a new point is added to the Stroke, it can be ignored if the cullDistance is higher than the distance from the last point. This is situationally good, I believe, but might not help you much, since you already do some "cleaning" of the point data sets
Thank you, IonSwitz!
Now I use the FastStroke in my app that gives me a satisfactory quality of visualization and performance. But it very good news! I'll try it and post here my experience soon. Thank you very much! ;)
IonSwitz, sorry that took so long to reply! I tried your new solution and want to tell you that it's very clean and good idea to transform existing geometry instead of create new. However, the problem with the artifacts in the Stroke class still remained in some cases, so I use the FastStroke class. I've added to it your adjustThicknessOfGeometry function and now it works faster in zoom animations. As for cullDistance functionality it would be nice if it were somehow integrated into the adjustThicknessOfGeometry func. Otherwise, I need to recreate all geometry again to use the 'cullDistance' (in zoom animations) instead of use adjustThicknessOfGeometry transformation. But I understand that this is not possible.
ps. Sorry for my eng, I hope you understand what I keep in mind ;)
Hello again. Yes, I understand how you mean, and don't worry about your English :)
I will look into such an integration, but I am not sure if it will be fully possible. Can I ask how many data points you have in your plots?`It sounds like there are quite many :)
Hello, IonSwitz! Thanx ;) "How many data points...?" - Oh, this is a hard question. I have not so many data points. It sounds like one or two thousands. But the difficulty lies in the fact that I need to draw smooth curves (bezier). I tried to use the Loop-Blinn method (something like http://blog.bwhiting.co.uk/?p=423) and draw all in the fragment shader, but it has so many troubles... Now I use your curveTo() realization, adapted to FastStroke class - and this means that I need to have many straight segments to make a curve really smooths. So there are very many "data points" ;)
Hi, guys! I've got a problem when trying to scale the stroke, keeping the thickness. When I change the stroke thickness to some large value, it draws incorrectly.
Please, look at the picture:![img](https://cloud.githubusercontent.com/assets/11996733/7227539/1eb2af70-e75a-11e4-85ff-9520b4e6ff34.png)
Here is project src: https://www.dropbox.com/s/om7v84i2iibpp53/pathTest.zip?dl=0
Thanks!