Improve native rendering. Sort rendering area based on area

This commit is contained in:
Victor Shcherb 2012-09-13 21:51:57 +02:00
parent 4c6c68e8b1
commit b2668c3429
5 changed files with 139 additions and 107 deletions

View file

@ -122,11 +122,13 @@ public class PoiFiltersHelper {
} else if(UDF_SIGHTSEEING.equals(key)){
putAll(types, AmenityType.HISTORIC);
putAll(types, AmenityType.TOURISM);
putAll(types, AmenityType.OSMWIKI);
putValues(types, AmenityType.OTHER, "place_of_worship");
} else if(UDF_FOR_TOURISTS.equals(key)){
putAll(types, AmenityType.HISTORIC);
putAll(types, AmenityType.TOURISM);
putAll(types, AmenityType.FINANCE);
putAll(types, AmenityType.OSMWIKI);
putValues(types, AmenityType.OTHER, "place_of_worship", "internet_access", "embassy","emergency_phone","marketplace",
"post_office","telephone", "toilets");
} else if(UDF_FUEL.equals(key)){

View file

@ -172,7 +172,7 @@ std::string RenderingContext::getReshapedString(const std::string& src) {
}
inline double getPowZoom(float zoom){
double getPowZoom(float zoom){
if(zoom >= 0 && zoom - floor(zoom) < 0.05f){
return 1 << ((int)zoom);
} else {

View file

@ -162,8 +162,8 @@ public:
int visible;
int allObjects;
int lastRenderedKey;
class ElapsedTimer textRendering;
class ElapsedTimer nativeOperations;
ElapsedTimer textRendering;
ElapsedTimer nativeOperations;
// because they used in 3rd party functions
public :
@ -294,6 +294,8 @@ void purgeCachedBitmaps();
int get31TileNumberX(double longitude);
int get31TileNumberY( double latitude);
double getPowZoom(float zoom);
double getLongitudeFromTile(float zoom, double x) ;
double getLatitudeFromTile(float zoom, double y);

View file

@ -25,8 +25,18 @@
#include "binaryRead.h"
#include "textdraw.cpp"
#include "mapObjects.h"
#include "rendering.h"
struct MapDataObjectPrimitive {
MapDataObject* obj;
int typeInd;
float order;
int objectType;
};
const int MAX_V = 32;
void calcPoint(std::pair<int, int> c, RenderingContext* rc)
{
rc->pointCount++;
@ -360,6 +370,14 @@ void drawPolyline(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas
if (!rendered || !updatePaint(req, paint, 0, 0, rc)) {
return;
}
int shadowColor = req->getIntPropertyValue(req->props()->R_SHADOW_COLOR);
int shadowRadius = req->getIntPropertyValue(req->props()->R_SHADOW_RADIUS);
if(drawOnlyShadow && shadowRadius == 0) {
return;
}
if(shadowColor == 0) {
shadowColor = rc->getShadowRenderingColor();
}
int oneway = 0;
if (rc->getZoom() >= 16 && pair.first == "highway") {
if (mObj->containsAdditional("oneway", "yes")) {
@ -377,6 +395,7 @@ void drawPolyline(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas
float prevx;
float prevy;
bool intersect = false;
int prevCross = 0;
for (; i < length; i++) {
calcPoint(mObj->points.at(i), rc);
if (i == 0) {
@ -388,22 +407,22 @@ void drawPolyline(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas
path.lineTo(rc->calcX, rc->calcY);
}
if (!intersect) {
if (rc->calcX >= 0 && rc->calcY >= 0 && rc->calcX < rc->getWidth()&& rc->calcY < rc->getHeight()) {
if (rc->calcX >= 0 && rc->calcY >= 0 && rc->calcX < rc->getWidth() && rc->calcY < rc->getHeight()) {
intersect = true;
}
if (!intersect && i > 0) {
if ((rc->calcX < 0 && prevx < 0) || (rc->calcY < 0 && prevy < 0) ||
(rc->calcX> rc->getWidth() && prevx > rc->getWidth())
|| (rc->calcY > rc->getHeight() && prevy > rc->getHeight())) {
intersect = false;
} else {
intersect = true;
} else {
int cross = 0;
cross |= (rc->calcX < 0 ? 1 : 0);
cross |= (rc->calcX > rc->getWidth() ? 2 : 0);
cross |= (rc->calcY < 0 ? 4 : 0);
cross |= (rc->calcY > rc->getHeight() ? 8 : 0);
if(i > 0) {
if((prevCross & cross) == 0) {
intersect = true;
}
}
prevCross = cross;
}
}
prevx = rc->calcX;
prevy = rc->calcY;
}
if (!intersect) {
@ -412,11 +431,6 @@ void drawPolyline(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas
if (i > 0) {
if (drawOnlyShadow) {
int shadowColor = req->getIntPropertyValue(req->props()->R_SHADOW_COLOR);
int shadowRadius = req->getIntPropertyValue(req->props()->R_SHADOW_RADIUS);
if(shadowColor == 0) {
shadowColor = rc->getShadowRenderingColor();
}
drawPolylineShadow(cv, paint, rc, &path, shadowColor, shadowRadius);
} else {
if (updatePaint(req, paint, -2, 0, rc)) {
@ -467,9 +481,7 @@ void drawPolygon(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas*
rc->visible++;
SkPath path;
int i = 0;
float prevx;
float prevy;
bool intersect = false;
bool containsPoint = false;
int bounds = 0;
for (; i < length; i++) {
calcPoint(mObj->points.at(i), rc);
@ -478,35 +490,36 @@ void drawPolygon(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas*
} else {
path.lineTo(rc->calcX, rc->calcY);
}
xText += rc->calcX;
yText += rc->calcY;
if (!intersect) {
float tx = rc->calcX;
if (tx < 0) {
tx = 0;
}
if (tx > rc->getWidth()) {
tx = rc->getWidth();
}
float ty = rc->calcX;
if (ty < 0) {
ty = 0;
}
if (ty > rc->getHeight()) {
ty = rc->getHeight();
}
xText += tx;
yText += ty;
if (!containsPoint) {
if (rc->calcX >= 0 && rc->calcY >= 0 && rc->calcX < rc->getWidth() && rc->calcY < rc->getHeight()) {
intersect = true;
containsPoint = true;
}
bounds |= (rc->calcX < 0 ? 1 : 0);
bounds |= (rc->calcX >= rc->getWidth() ? 2 : 0);
bounds |= (rc->calcY < 0 ? 4 : 0);
bounds |= (rc->calcY >= rc->getHeight() ? 8 : 0);
if (!intersect && i > 0) {
if ((rc->calcX < 0 && prevx < 0) || (rc->calcY < 0 && prevy < 0)
|| (rc->calcX > rc->getWidth() && prevx > rc->getWidth())
|| (rc->calcY > rc->getHeight() && prevy > rc->getHeight())) {
intersect = false;
} else {
intersect = true;
}
}
}
}
if(!intersect){
xText /= length;
yText /= length;
if(!containsPoint){
if(bounds == 15) {
path.reset();
path.moveTo(0, 0);
path.lineTo(0, rc->getWidth());
path.lineTo(rc->getHeight(), rc->getWidth());
path.lineTo(rc->getHeight(), 0);
path.close();
xText = rc->getWidth() / 2;
yText = rc->getHeight() / 2;
} else {
@ -534,7 +547,7 @@ void drawPolygon(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas*
PROFILE_NATIVE_OPERATION(rc, cv->drawPath(path, *paint));
}
renderText(mObj, req, rc, pair.first, pair.second, xText / length, yText / length, NULL);
renderText(mObj, req, rc, pair.first, pair.second, xText, yText, NULL);
}
void drawPoint(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas* cv, SkPaint* paint,
@ -579,18 +592,30 @@ void drawPoint(MapDataObject* mObj, RenderingRuleSearchRequest* req, SkCanvas* c
}
void drawObject(RenderingContext* rc, MapDataObject* mObj, SkCanvas* cv, RenderingRuleSearchRequest* req,
SkPaint* paint, int l, int renderText, int drawOnlyShadow, int t) {
rc->allObjects++;
tag_value pair = mObj->types.at(l);
if (t == 1 && !drawOnlyShadow) {
// point
drawPoint(mObj, req, cv, paint, rc, pair, renderText);
} else if (t == 2) {
drawPolyline(mObj, req, cv, paint, rc, pair, mObj->getSimpleLayer(), drawOnlyShadow);
} else if (t == 3 && !drawOnlyShadow) {
// polygon
drawPolygon(mObj, req, cv, paint, rc, pair);
void drawObject(RenderingContext* rc, SkCanvas* cv, RenderingRuleSearchRequest* req,
SkPaint* paint, vector<MapDataObjectPrimitive>& array, int objOrder) {
double limit = 100;
for (int i = 0; i < array.size(); i++) {
rc->allObjects++;
MapDataObject* mObj = array[i].obj;
tag_value pair = mObj->types.at(array[i].typeInd);
if (objOrder == 0) {
if (array[i].order < limit) {
return;
}
// polygon
drawPolygon(mObj, req, cv, paint, rc, pair);
} else if (objOrder == 1) {
drawPolyline(mObj, req, cv, paint, rc, pair, mObj->getSimpleLayer(), true);
} else if (objOrder == 2) {
drawPolyline(mObj, req, cv, paint, rc, pair, mObj->getSimpleLayer(), false);
} else if (objOrder == 3) {
drawPoint(mObj, req, cv, paint, rc, pair, array[i].typeInd == 0);
}
if (i % 25 == 0 && rc->interrupted()) {
return;
}
}
}
@ -635,12 +660,30 @@ void drawIconsOverCanvas(RenderingContext* rc, SkCanvas* canvas)
}
}
UNORDERED(map)<int, std::vector<int> > sortObjectsByProperOrder(std::vector <MapDataObject* > mapDataObjects,
RenderingRuleSearchRequest* req, RenderingContext* rc) {
UNORDERED(map)<int, std::vector<int> > orderMap;
double polygonArea(MapDataObject* obj, float mult) {
double area = 0.;
int j = obj->points.size() - 1;
for (int i = 0; i < obj->points.size(); i++) {
int_pair x = obj->points[i] ;
int_pair y = obj->points[j];
area += (y.first + ((float) x.first) )* (y.second- ((float)x.second));
j = i;
}
return std::abs(area) * mult * mult * .5;
}
bool sortByOrder(const MapDataObjectPrimitive& i,const MapDataObjectPrimitive& j) { return (i.order<j.order); }
bool sortByRevOrder(const MapDataObjectPrimitive& i,const MapDataObjectPrimitive& j) { return (i.order>j.order); }
void sortObjectsByProperOrder(std::vector <MapDataObject* > mapDataObjects,
RenderingRuleSearchRequest* req, RenderingContext* rc,
std::vector<MapDataObjectPrimitive>& polygonsArray, std::vector<MapDataObjectPrimitive>& pointsArray,
std::vector<MapDataObjectPrimitive>& linesArray) {
if (req != NULL) {
req->clearState();
const int size = mapDataObjects.size();
float mult = 1. / getPowZoom(max(31 - (rc->getZoom() + 8), 0));
int i = 0;
for (; i < size; i++) {
uint32_t sh = i << 8;
@ -657,11 +700,22 @@ UNORDERED(map)<int, std::vector<int> > sortObjectsByProperOrder(std::vector <Map
if (req->searchRule(RenderingRulesStorage::ORDER_RULES)) {
int objectType = req->getIntPropertyValue(req->props()->R_OBJECT_TYPE);
int order = req->getIntPropertyValue(req->props()->R_ORDER);
orderMap[(order << 2)|objectType].push_back(sh + j);
MapDataObjectPrimitive mapObj;
mapObj.objectType = objectType;
mapObj.order = order;
mapObj.typeInd = j;
mapObj.obj = mobj;
// polygon
if(objectType == 3) {
// add icon point all the time
orderMap[(128 << 2)|1].push_back(sh + j);
MapDataObjectPrimitive pointObj = mapObj;
pointObj.objectType = 1;
mapObj.order = polygonArea(mobj, mult);
polygonsArray.push_back(mapObj);
pointsArray.push_back(pointObj);
} else if(objectType == 1) {
pointsArray.push_back(mapObj);
} else {
linesArray.push_back(mapObj);
}
if (req->getIntPropertyValue(req->props()->R_SHADOW_LEVEL) > 0) {
rc->shadowLevelMin = std::min(rc->shadowLevelMin, order);
@ -672,8 +726,10 @@ UNORDERED(map)<int, std::vector<int> > sortObjectsByProperOrder(std::vector <Map
}
}
sort(polygonsArray.begin(), polygonsArray.end(), sortByRevOrder);
sort(pointsArray.begin(), pointsArray.end(), sortByOrder);
sort(linesArray.begin(), linesArray.end(), sortByOrder);
}
return orderMap;
}
void doRendering(std::vector <MapDataObject* > mapDataObjects, SkCanvas* canvas,
@ -683,53 +739,23 @@ void doRendering(std::vector <MapDataObject* > mapDataObjects, SkCanvas* canvas,
SkPaint* paint = new SkPaint;
paint->setAntiAlias(true);
// put in order map
UNORDERED(map)<int, std::vector<int> > orderMap = sortObjectsByProperOrder(mapDataObjects, req, rc);
std::set<int> keys;
UNORDERED(map)<int, std::vector<int> >::iterator it = orderMap.begin();
std::vector<MapDataObjectPrimitive> polygonsArray;
std::vector<MapDataObjectPrimitive> pointsArray;
std::vector<MapDataObjectPrimitive> linesArray;
sortObjectsByProperOrder(mapDataObjects, req, rc, polygonsArray, pointsArray, linesArray);
rc->lastRenderedKey = 0;
while (it != orderMap.end()) {
keys.insert(it->first);
it++;
drawObject(rc, canvas, req, paint, polygonsArray, 0);
rc->lastRenderedKey = 5;
if (rc->getShadowRenderingMode() > 1) {
drawObject(rc, canvas, req, paint, linesArray, 1);
}
bool shadowDrawn = false;
for (std::set<int>::iterator ks = keys.begin(); ks != keys.end(); ks++) {
if (!shadowDrawn && ((*ks)>>2) >= rc->shadowLevelMin && ((*ks)>>2) <= rc->shadowLevelMax && rc->getShadowRenderingMode() > 1) {
for (std::set<int>::iterator ki = ks; ki != keys.end(); ki++) {
if (((*ki)>>2) > rc->shadowLevelMax || rc->interrupted()) {
break;
}
std::vector<int> list = orderMap[*ki];
for (std::vector<int>::iterator ls = list.begin(); ls != list.end(); ls++) {
int i = *ls;
int ind = i >> 8;
int l = i & 0xff;
MapDataObject* mapObject = mapDataObjects.at(ind);
rc->lastRenderedKey = 40;
drawObject(rc, canvas, req, paint, linesArray, 2);
rc->lastRenderedKey = 60;
// show text only for main type
drawObject(rc, mapObject, canvas, req, paint, l, l == 0, true, (*ki)&3);
}
}
shadowDrawn = true;
}
std::vector<int> list = orderMap[*ks];
for (std::vector<int>::iterator ls = list.begin(); ls != list.end(); ls++) {
int i = *ls;
int ind = i >> 8;
int l = i & 0xff;
MapDataObject* mapObject = mapDataObjects.at(ind);
// show text only for main type
drawObject(rc, mapObject, canvas, req, paint, l, l == 0, false, (*ks)&3);
}
rc->lastRenderedKey = (*ks) >>2;
if (rc->interrupted()) {
return;
}
}
drawObject(rc, canvas, req, paint, pointsArray, 3);
rc->lastRenderedKey = 125;
drawIconsOverCanvas(rc, canvas);

View file

@ -9,4 +9,6 @@
void doRendering(std::vector <MapDataObject* > mapDataObjects, SkCanvas* canvas,
RenderingRuleSearchRequest* req, RenderingContext* rc);
#endif