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

Line stipple / texture rendering problems #1005

Closed
demiantres opened this issue Jan 8, 2023 · 28 comments
Closed

Line stipple / texture rendering problems #1005

demiantres opened this issue Jan 8, 2023 · 28 comments
Labels
Milestone

Comments

@demiantres
Copy link

The commit "707e1c406984bb22567133cea426bf6519246a97" (707e1c4) introduces new rendering problems with OpenAndroMaps Elements/Elevate themes:

Before (I is ok, II is no ok):
image

after the patch (I is not ok, II is ok):
image

@devemux86
Copy link
Collaborator

Thanks for the report.
Please also write the theme rules that appear in the image and coordinates of the area.

Line textures did not work properly, see #983 and #985.
Now it's better with a new implementation, but there's always room for improvement. 🙂

@demiantres
Copy link
Author

The problem are the hardcoded "*8" values:
b.stipple *= 8; f *= 8;

The screenshots show the OpenAndroMaps Austria map, with Elements style at 47.63082°, 15.69521°.

@demiantres
Copy link
Author

demiantres commented Jan 10, 2023

When removing the "*8" factor then I is drawn correctly, but II is wrong again.
The problem occurs in tags like these:

<rule e="way" k="tracktype" v="~">
	<line stroke="#aad0c7" stroke-width="0.95" stroke-dasharray="4,1,11,1,4,5" stroke-linecap="butt" />
</rule>

@devemux86
Copy link
Collaborator

devemux86 commented Jan 10, 2023

Thanks for the details.

Mapsforge and VTM are different map engines and their themes are not fully compatible.
So some compromises are needed and the result should not be expected to be the same.

These values are active in the case of Mapsforge themes.
If there is a better way to read / parse a Mapsforge theme, we can certainly check it.

@demiantres
Copy link
Author

demiantres commented Jan 10, 2023

What I don't understand is why the values have to multiplied by factor 8 for Mapsforge themes? The stipple size is already defined by means of the theme's "stroke-dasharray" attribute, isn't it?

@devemux86
Copy link
Collaborator

devemux86 commented Jan 10, 2023

Can you try absolute values, does it work with all Mapsforge theme rules and everywhere?

As they are different engines, value 2 in Mapsforge could need 4 in OpenGL (or vice versa),
trying to look "similar" and still not succeeding in the same rendering.

Rendering stipples in VTM themes seems to work properly (see the VTM themes).

Rendering Mapsforge themes with VTM engine is different, a translation is needed.
We still need to find the most compatible translation of Mapsforge themes.

@demiantres
Copy link
Author

Actually this code (starting with line 613 in XmlThemeBuilder.java) ignores the space length:

        if (b.dashArray != null) {
            // Stroke dash array
            if (b.dashArray.length == 2) {
                b.randomOffset = false;
                b.stipple = b.dashArray[0] < 1 ? 1 : (int) b.dashArray[0];
                if (mTheme.isMapsforgeTheme())
                    b.stipple *= 8;
                b.stippleWidth = 1;
                b.stippleColor = Color.TRANSPARENT;
                b.dashArray = null;
            } else {

It would only make sense if the check is if (b.dashArray.length == 1)?

@devemux86
Copy link
Collaborator

In the case of a 2-value dash array, it is better for rendering and performance to use stipples instead of textures.
(stipples can work with 2 values)

What is space length?

Odd number of dash array entries is duplicated, so 1 becomes 2.
We probably need to do the duplication of 1 before that if too.

@devemux86 devemux86 changed the title Commit 707e1c406984bb22567133cea426bf6519246a97 rendering problems Line stipple / texture rendering problems Jan 10, 2023
@demiantres
Copy link
Author

Sorry, I meant this with "space length": dashArray = [2, 10]; means draw 2 pixels, 10 pixel spaces, draw 2 pixels, ...

In the case of a 2-value dash array, it is better for rendering and performance to use stipples instead of textures.
Yes, but the code does not do this but renders only dashes of size dashArray[0]?

For testing purposes I changed the check if (b.dashArray.length == 2) to if (b.dashArray.length == 1) and removed the *8 factors. Actually this works exactly as intended. The problem is that the render themes (i.e. OpenAndroMaps Elevate) are optimized for the Mapsforge renderer (as you wrote) and the Mapsforge render seems to handle dashed lines incorrectly.

@devemux86
Copy link
Collaborator

devemux86 commented Jan 10, 2023

I meant this with "space length": dashArray = [2, 10]; means draw 2 pixels, 10 pixel spaces, draw 2 pixels, ...

Different values mean texture rendering instead of stipples.

I changed the check if (b.dashArray.length == 2) to if (b.dashArray.length == 1)

Then dash arrays with 2 values will use the texture rendering.
Texture rendering is not visually good, so it is better to avoid it.

The problem is that the render themes (i.e. OpenAndroMaps Elevate) are optimized for the Mapsforge renderer

Indeed and so far there is no easy solution to properly render Mapsforge / OpenAndroMaps / Freizeitkarte themes in VTM.

It's all a never-ending cycle, making one case better and another worse.

@demiantres
Copy link
Author

Here are some results with my changes mentioned above (VTM):
image

Mapsforge engine:
image

VTM engine with your patches:
image

@devemux86
Copy link
Collaborator

devemux86 commented Jan 10, 2023

I changed the check if (b.dashArray.length == 2) to if (b.dashArray.length == 1) and removed the *8 factors

Let's try your suggestions and see how it works.
The factor was made optional in Parameters (default 1).

Then there is the case that Mapsforge dash arrays with small values do not appear as dashed lines in VTM (#983).

@demiantres
Copy link
Author

Thanks. Another thing is that the line widths do not fully scale, i.e. the Mapsforge renderer fills the whole street width with the orange/white pattern, while the VTM renderer does not fill it in higher zoom levels. It seems as if the VTM renderer has a maximum width limit but I am still trying to figure out how this actually works.

@devemux86
Copy link
Collaborator

devemux86 commented Jan 10, 2023

There is the parameter fixed in style (and fix in VTM themes).
However, the results still cannot be like Mapsforge.

@devemux86
Copy link
Collaborator

Also OpenGL has limits, see #121 (comment).

@demiantres
Copy link
Author

Better change this line in LineTexBucket:

float s = scale / div;

to

float s = Math.sqrt(scale / div);

Now lines (even with thin dash pattern) look much better, almost like Mapsforge.

@devemux86
Copy link
Collaborator

devemux86 commented Jan 10, 2023

For reference, Berlin map with Freizeitkarte theme and MAPSFORGE_DASH_FACTOR set as 1 or 8:
(the green line has different renderings in 1st image, depends on scale between zoom levels)
Freizeitkarte1
Freizeitkarte8

@demiantres
Copy link
Author

Better (move this into the loop):

float s;
if (line.fixed)
  s = scale / div;
else
  s = Math.sqrt(scale / div);

@demiantres
Copy link
Author

With this fix you no longer need to set the MAPSFORGE_DASH_FACTOR imaho.

@devemux86
Copy link
Collaborator

It is still the same small dashes and the green line still has 2 different renderings between zoom levels.

@demiantres
Copy link
Author

I can reproduce the problem with the Freizeitkarte too. OAM maps + themes seem to work fine though.

@demiantres
Copy link
Author

I think the problem is this check in the XmlThemeBuilder:

if (f < 1) f = 1;

Freizeitkarte uses dash sizes < 1, while OAM uses sizes >= 1.

@devemux86
Copy link
Collaborator

devemux86 commented Jan 10, 2023

Android / Java bitmaps used in line dashed textures have integer width and height.
(maybe the dash arrays with <1 need the multiplier)

@demiantres
Copy link
Author

Yes, this is what I meant.

@demiantres
Copy link
Author

demiantres commented Jan 11, 2023

The Mapsforge renderer uses this:


#define STROKE_INCREASE 1.5
#define STROKE_MIN_ZOOM_LEVEL 12

void MFRenderContext::setScaleStrokeWidth(int zoomLevel)
{
    if (this->renderTheme)
    {
        int zoomLevelDiff = qMax(zoomLevel - STROKE_MIN_ZOOM_LEVEL, 0);
        this->renderTheme->scaleStrokeWidth(static_cast<float>(qPow(STROKE_INCREASE, zoomLevelDiff)), this->rendererJob->tile.zoomLevel);
    }
}

Maybe we can use this somehow...

devemux86 added a commit that referenced this issue Jan 11, 2023
devemux86 added a commit that referenced this issue Jan 11, 2023
@devemux86
Copy link
Collaborator

See #1008.

@devemux86
Copy link
Collaborator

devemux86 commented Jan 11, 2023

Mapsforge rendering at large zooms isn't the best (extending width but not dash length),
so we have to be careful what comparison we make.

@devemux86 devemux86 added the bug label Jan 23, 2023
@devemux86 devemux86 added this to the 0.19.0 milestone Jan 24, 2023
@devemux86
Copy link
Collaborator

With #1008 it should be better.
If more work is needed, please create new issues with examples and suggestions for code improvement.

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

No branches or pull requests

2 participants