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

Tile rendering with buffer #1257

Open
vyskocil opened this issue May 1, 2022 · 13 comments
Open

Tile rendering with buffer #1257

vyskocil opened this issue May 1, 2022 · 13 comments
Labels
feature For issues and pull request that request or implement a new feature help wanted Signal that help of other is appreciated renderer For issues in the content of the rendering engine

Comments

@vyskocil
Copy link
Collaborator

vyskocil commented May 1, 2022

I wish it could be possible to configure tile rendering with some given buffer size around the drawing area to avoid cut labels at tile edges. Maybe this is already possible with some drawing parameters but I could not find it... I remember there was the SetDropNotVisiblePointLabels parameter, but I could not understand how it could work with tile rendering.
Here is a schematics to explain what I want to achieve :

Tile with buffer

@vyskocil vyskocil added the feature For issues and pull request that request or implement a new feature label May 1, 2022
@Karry
Copy link
Collaborator

Karry commented May 1, 2022

Hi Vlad.

If you are using LabelLayouter, you may use LabelLayouter::SetLayoutOverlap to setup such "buffer". All backends (except OpenGL) do that. See MapPainterIOS::BeforeDrawing method for example:

labelLayouter.SetViewport(DoubleRectangle(0, 0, CGBitmapContextGetWidth(cg), CGBitmapContextGetHeight(cg)));
labelLayouter.SetLayoutOverlap(projection.ConvertWidthToPixel(parameter.GetLabelLayouterOverlap()));

MapParameter::labelLayouterOverlap is 30 mm by default. Does it work for you?

@vyskocil
Copy link
Collaborator Author

vyskocil commented May 2, 2022

Hi @Karry !

Thank you for the response !
I tried to set MapParameter::labelLayouterOverlap to 100 then 1000 with no luck in some cases like the following :

IMG_3607

IMG_3608

Do you know why there are some missing tile border in this one ? I remarked that it's the case every some rows...
To display the tile borders I used :

[MAG world-] {
   [TYPE _osm_tile_border] WAY {color: #222222; displayWidth: 0.2mm; }
}

IMG_3609

@Karry
Copy link
Collaborator

Karry commented May 3, 2022

Do you know why there are some missing tile border in this one ? I remarked that it's the case every some rows...

it seems to be bug in _osm_tile_border synthetic type. It is not rendered for bottom row in "plane" rendering...

@Karry
Copy link
Collaborator

Karry commented May 3, 2022

When I do few experiments with Demos/Tiler, I realized that label layouter overlap is not enough. You need to use some overlap for loaded data as well. Because label layouter cannot know about labels behind the corner when you don't provide data about them...

Btw, for layouter debugging, you may define DEBUG_LABEL_LAYOUTER macro. Then you will see line about every tested label in layouter, it will help you to figure out where the problem may be.

@vyskocil
Copy link
Collaborator Author

vyskocil commented May 14, 2023

I'm looking at this issue again because I could see a lot of cut labels using the tile renderer, for example :

IMG_A8B286285CDC-1

When drawing the map the code I'm using is something like :

mapServices->LookupTiles(projection, tiles);
mapServices->LoadMissingTileData(searchParameter, styleConfigs, tiles);
datas.ClearDBData();
mapServices->AddTileDataToMapData(tiles, datas);

Maybe LoadMissingTileData could have a OverdrawSize argument (or in the SearchParamater) that would enlarge the source of the fetched data around the tile. It could be in TileSize unit, 1.0 meaning no overdraw data fetching, 1.5 would add half the tile size up, down, left and right,...

@Karry , @Framstag what's you opinion on this ?

@vyskocil vyskocil added help wanted Signal that help of other is appreciated renderer For issues in the content of the rendering engine labels May 14, 2023
@Karry
Copy link
Collaborator

Karry commented May 14, 2023

Hi Vlad. We may add overdraw argument, but it is not the only option. In Qt tile renderer, I add one tile dimension (1/2 on each side) to "lookupProjection". Here for reference: TiledMapRenderer.cpp:297

@vyskocil
Copy link
Collaborator Author

vyskocil commented Jun 1, 2023

Hi @Karry !
Thank you for the reference in Qt TiledMapRenderer, I tried this solution but without much success for now...
At first I had to report some of the OSMTile methods in my code, maybe these class should be moved from libosmscout-map-qt to core libosmscout-map library as it contains some useful methods for every backend.
Then I understood that my code needs to use TileProjection for the drawing itself and a MercatorProjection (dataProjection) based on the TileProjection but larger, for my test there is more than the size of the map tile around the drawn tile ie the MercatorProjection is 3x the width and height of the TileProjection.

I use the MercatorProjection to fetch the map data like this :

std::list<osmscout::TileRef> tiles;
ctx->mapServices[i]->LookupTiles(dataProjection,tiles);
ctx->mapServices[i]->LoadMissingTileData(searchParameter, *(ctx->styleConfigs[i]),tiles);
ctx->datas[i].ClearDBData();
ctx->mapServices[i]->AddTileDataToMapData(tiles, ctx->datas[i]);

is it right ? is LoadMissingTileData() dependent on the projection otherwise than through the tiles argument ?

I think it would be very handy if the core map library could provide this mechanism to be easily be used within each backend or application needing this feature, don't you think so ?

@Framstag
Copy link
Owner

Framstag commented Jun 4, 2023

I already suggested to create a libosmscout-client library to move client-specific but device agnostic code there.

THe problem that @Karry has, that he still needs some glueing code to get things smoothly running in the Qt world. So what wents into the client and what in the client-qt library has to be a case by case decision and good APIs will likely be important.

@Karry
Copy link
Collaborator

Karry commented Jun 6, 2023

Your code should be correct. It is possible that iOS renderer is using differet label layouter parameters?

I would love to move generic code from Qt client library to main lib. Over the years, It contains various useful modules not specific to QML. Problem is that this code is heavily using Qt signals, networking abstraction, threading... C++ standard does not provide simple replacement for those. Do you know some lightweight library that have similar capabilities like Qt signals?

@vyskocil
Copy link
Collaborator Author

vyskocil commented Jun 7, 2023

Thank @Karry for the responses !
I'm looking at the layouter parameters and how it was coded in libosmscoup-map-iOSX, but I'm seeing that I followed what has been done in map-qt but there is a potential delegateLabelLayouter in map-qt, what's the intent of this ?
I also have a question about :

double labelLayouterOverlap; //!< Overlap of visible area used by label layouter in mm (default 30)

It's defined as using mm but I could see in the map-qt code that there is a conversion in pixels before setting this parameter :

void MapPainterQt::BeforeDrawing(const StyleConfig& /*styleConfig*/,
                                   const Projection& projection,
                                   const MapParameter& parameter,
                                   const MapData& /*data*/)
  {
    labelLayouter.SetViewport(DoubleRectangle(0, 0, painter->window().width(), painter->window().height()));
    labelLayouter.SetLayoutOverlap(projection.ConvertWidthToPixel(parameter.GetLabelLayouterOverlap()));
  }

@Karry
Copy link
Collaborator

Karry commented Jun 7, 2023

delegateLabelLayouter is there for the case when multiple databases are rendered. Labels from all Painters are registered to the label layouter of the last Painter. That way, labels on database boundaries do not collide.

With overlap, you are correct. Value in MapParameter is in millimeters, but LabelLayouter expect overlap in pixels.

@Framstag
Copy link
Owner

Framstag commented Jun 8, 2023

I'll start implementing a frame for a general libosmscout-client library as soon as I have some spare time.

IMHO the library must be UI implementation agnostic. So It should avoid threads but should only offer lambda functions or similar that can be used under different thread APIs. It may additionally offer a C++ standard based thread implementation though, too.

Other code (networking) might use callback that have to be filled in by the concrete client to offer a concrete implementation.

Boost would be an obvious candidate for some 3rd party libraries, but may make building application more difficult.

Regarding signal/slot. I have no idea. I implemented various model/viewer/controller code myself in the past (see libillumination) which worked out well and we can copy the code - but I doubt that such approach will help in Qt.

I would suggest to start with the obvious movable code and see how far we come and how usable the code is.

@Karry
Copy link
Collaborator

Karry commented Jun 9, 2023

I was looking to all the things that client-qt library is using in core components and it would be really hard to cut Qt off :-( I can imagine to split this library to two parts: core, that is using just QtCore module and the rest, that is providing models to QML UI.

Replacing all the QtCore utilities that library is using would be inventing the wheel...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature For issues and pull request that request or implement a new feature help wanted Signal that help of other is appreciated renderer For issues in the content of the rendering engine
Projects
None yet
Development

No branches or pull requests

3 participants