Open vyskocil opened 2 years ago
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?
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 :
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; }
}
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...
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.
I'm looking at this issue again because I could see a lot of cut labels using the tile renderer, for example :
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 ?
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
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 ?
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.
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?
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()));
}
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.
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.
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...
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 :