Calculate text collisions properly
This commit is contained in:
parent
4fd9f75b69
commit
f2c5a75c94
5 changed files with 83 additions and 33 deletions
|
@ -8,7 +8,7 @@
|
||||||
#include <SkPath.h>
|
#include <SkPath.h>
|
||||||
#include <SkBitmap.h>
|
#include <SkBitmap.h>
|
||||||
|
|
||||||
//#define DEBUG_NAT_OPERATIONS
|
#define DEBUG_NAT_OPERATIONS
|
||||||
|
|
||||||
#ifdef DEBUG_NAT_OPERATIONS
|
#ifdef DEBUG_NAT_OPERATIONS
|
||||||
#define NAT_COUNT(rc, op) rc->nativeOperations.pause(); op; rc->nativeOperations.start()
|
#define NAT_COUNT(rc, op) rc->nativeOperations.pause(); op; rc->nativeOperations.start()
|
||||||
|
@ -81,7 +81,7 @@ jfieldID getFid(jclass cls,const char* fieldName, const char* sig )
|
||||||
}
|
}
|
||||||
|
|
||||||
class watcher {
|
class watcher {
|
||||||
int elapsedTime;
|
long elapsedTime;
|
||||||
bool enableFlag;
|
bool enableFlag;
|
||||||
// timeval startInit;
|
// timeval startInit;
|
||||||
// timeval endInit;
|
// timeval endInit;
|
||||||
|
@ -94,6 +94,7 @@ public:
|
||||||
watcher() {
|
watcher() {
|
||||||
elapsedTime = 0;
|
elapsedTime = 0;
|
||||||
enableFlag = true;
|
enableFlag = true;
|
||||||
|
run = false;
|
||||||
}
|
}
|
||||||
void enable(){
|
void enable(){
|
||||||
enableFlag = true;
|
enableFlag = true;
|
||||||
|
|
|
@ -223,7 +223,7 @@ bool calculatePathToRotate(RenderingContext* rc, TextDrawInfo* p) {
|
||||||
py += points[i].fY - points[i - 1].fY;
|
py += points[i].fY - points[i - 1].fY;
|
||||||
}
|
}
|
||||||
if (px != 0 || py != 0) {
|
if (px != 0 || py != 0) {
|
||||||
p->pathRotate = std::atan2(py, px) * 180 / M_PI;
|
p->pathRotate = std::atan2(py, px);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -319,10 +319,10 @@ bool calculatePathToRotate(RenderingContext* rc, TextDrawInfo* p) {
|
||||||
float ox = -py;
|
float ox = -py;
|
||||||
float oy = px;
|
float oy = px;
|
||||||
if(plen > 0) {
|
if(plen > 0) {
|
||||||
float rot = std::atan2(py, px) * 180 / M_PI;
|
float rot = std::atan2(py, px);
|
||||||
if (rot < 0) rot += 360;
|
if (rot < 0) rot += M_PI * 2;
|
||||||
if (rot > 90 && rot < 270) {
|
if (rot > M_PI_2 && rot < 3 * M_PI_2) {
|
||||||
rot += 180;
|
rot += M_PI;
|
||||||
inverse = true;
|
inverse = true;
|
||||||
ox = -ox;
|
ox = -ox;
|
||||||
oy = -oy;
|
oy = -oy;
|
||||||
|
@ -354,27 +354,66 @@ bool calculatePathToRotate(RenderingContext* rc, TextDrawInfo* p) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawTestBox(SkCanvas* cv, TextDrawInfo* text, SkPaint* paintIcon, SkPaint* paintText)
|
void drawTestBox(SkCanvas* cv, SkRect* r, float rot, SkPaint* paintIcon, std::string text, SkPaint* paintText)
|
||||||
{
|
{
|
||||||
cv->save();
|
cv->save();
|
||||||
cv->translate(text->bounds.centerX(),text->bounds.centerY());
|
cv->translate(r->centerX(),r->centerY());
|
||||||
cv->rotate(text->pathRotate);
|
cv->rotate(rot * 180 / M_PI);
|
||||||
SkRect r = SkRect::MakeLTRB(-text->bounds.width()/2, -text->bounds.height()/2,
|
SkRect rs = SkRect::MakeLTRB(-r->width()/2, -r->height()/2,
|
||||||
text->bounds.width()/2, text->bounds.height()/2);
|
r->width()/2, r->height()/2);
|
||||||
cv->drawRect(r, *paintIcon);
|
cv->drawRect(rs, *paintIcon);
|
||||||
if (paintText != NULL) {
|
if (paintText != NULL) {
|
||||||
cv->drawText(text->text.data(), text->text.length(), r.centerX(), r.centerY(),
|
cv->drawText(text.data(), text.length(), rs.centerX(), rs.centerY(),
|
||||||
*paintText);
|
*paintText);
|
||||||
}
|
}
|
||||||
cv->restore();
|
cv->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersect(TextDrawInfo* t, TextDrawInfo* s)
|
float sqr(float a){
|
||||||
{
|
return a*a;
|
||||||
// TODO rotation
|
|
||||||
return t->bounds.intersect(s->bounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool intersect(SkRect tRect, float tRot, TextDrawInfo* s)
|
||||||
|
{
|
||||||
|
float sRot = s->pathRotate;
|
||||||
|
if (abs(tRot) < M_PI / 15 && abs(sRot) < M_PI / 15) {
|
||||||
|
return tRect.intersect(s->bounds);
|
||||||
|
}
|
||||||
|
float dist = sqrt(sqr(tRect.centerX() - s->bounds.centerX()) + sqr(tRect.centerY() - s->bounds.centerY()));
|
||||||
|
if(dist < 3) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SkRect sRect = s->bounds;
|
||||||
|
|
||||||
|
// difference close to 90/270 degrees
|
||||||
|
if(abs(cos(tRot-sRot)) < 0.3 ){
|
||||||
|
// rotate one rectangle to 90 degrees
|
||||||
|
tRot += M_PI_2;
|
||||||
|
tRect = SkRect::MakeXYWH(tRect.centerX() - tRect.height() / 2, tRect.centerY() - tRect.width() / 2,
|
||||||
|
tRect.height(), tRect.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine difference close to 180/0 degrees
|
||||||
|
if(abs(sin(tRot-sRot)) < 0.3){
|
||||||
|
// rotate t box
|
||||||
|
// (calculate offset for t center suppose we rotate around s center)
|
||||||
|
float diff = atan2(tRect.centerY() - sRect.centerY(), tRect.centerX() - sRect.centerX());
|
||||||
|
diff -= sRot;
|
||||||
|
float left = sRect.centerX() + dist* cos(diff) - tRect.width()/2;
|
||||||
|
float top = sRect.centerY() - dist* sin(diff) - tRect.height()/2;
|
||||||
|
SkRect nRect = SkRect::MakeXYWH(left, top, tRect.width(), tRect.height());
|
||||||
|
return nRect.intersect(sRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO other cases not covered
|
||||||
|
return tRect.intersect(sRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect(TextDrawInfo* t, TextDrawInfo* s) {
|
||||||
|
// TODO
|
||||||
|
return t->bounds.intersect(s->bounds);
|
||||||
|
// return intersect(t->bounds, t->pathRotate, s);
|
||||||
|
}
|
||||||
std::vector<TextDrawInfo*> search;
|
std::vector<TextDrawInfo*> search;
|
||||||
bool findTextIntersection(SkCanvas* cv, RenderingContext* rc, quad_tree<TextDrawInfo*>& boundIntersections, TextDrawInfo* text,
|
bool findTextIntersection(SkCanvas* cv, RenderingContext* rc, quad_tree<TextDrawInfo*>& boundIntersections, TextDrawInfo* text,
|
||||||
SkPaint* paintText, SkPaint* paintIcon) {
|
SkPaint* paintText, SkPaint* paintIcon) {
|
||||||
|
@ -395,24 +434,27 @@ bool findTextIntersection(SkCanvas* cv, RenderingContext* rc, quad_tree<TextDraw
|
||||||
text->bounds.offset(text->centerX - text->bounds.width()/2, text->centerY - text->bounds.height()/2);
|
text->bounds.offset(text->centerX - text->bounds.width()/2, text->centerY - text->bounds.height()/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SkRect boundsSearch = text->bounds;
|
|
||||||
float v = -getDensityValue(rc, std::max(5.0f, text->minDistance));
|
|
||||||
// TODO min distance different !
|
|
||||||
boundsSearch.inset(v, v);
|
|
||||||
|
|
||||||
// for text purposes
|
// for text purposes
|
||||||
// drawTestBox(cv, text, paintIcon, paintText);
|
// drawTestBox(cv, &text->bounds, text->pathRotate, paintIcon, text->text, NULL/*paintText*/);
|
||||||
|
boundIntersections.query_in_box(text->bounds, search);
|
||||||
boundIntersections.query_in_box(boundsSearch, search);
|
|
||||||
for (uint i = 0; i < search.size(); i++) {
|
for (uint i = 0; i < search.size(); i++) {
|
||||||
TextDrawInfo* t = search.at(i);
|
TextDrawInfo* t = search.at(i);
|
||||||
if (intersect(text, t)) {
|
if (intersect(text, t)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (boundsSearch.intersect(t->bounds) && t->text == text->text) {
|
}
|
||||||
|
}
|
||||||
|
if(text->minDistance > 0) {
|
||||||
|
SkRect boundsSearch = text->bounds;
|
||||||
|
boundsSearch.inset(-getDensityValue(rc, std::max(5.0f, text->minDistance)), -getDensityValue(rc, 12));
|
||||||
|
// drawTestBox(cv, &boundsSearch, text->pathRotate, paintIcon, text->text, NULL/*paintText*/);
|
||||||
|
for (uint i = 0; i < search.size(); i++) {
|
||||||
|
TextDrawInfo* t = search.at(i);
|
||||||
|
if (t->minDistance > 0 && intersect(boundsSearch, text->pathRotate, t)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boundIntersections.insert(text, text->bounds);
|
boundIntersections.insert(text, text->bounds);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
Binary file not shown.
|
@ -1024,7 +1024,7 @@ public class OsmandSettings {
|
||||||
public final OsmandPreference<Boolean> TEST_ANIMATE_ROUTING = new BooleanPreference("animate_routing", false, true);
|
public final OsmandPreference<Boolean> TEST_ANIMATE_ROUTING = new BooleanPreference("animate_routing", false, true);
|
||||||
|
|
||||||
// this value string is synchronized with settings_pref.xml preference name
|
// this value string is synchronized with settings_pref.xml preference name
|
||||||
public final OsmandPreference<Boolean> NATIVE_RENDERING = new BooleanPreference("native_rendering", true, true);
|
public final OsmandPreference<Boolean> NATIVE_RENDERING = new BooleanPreference("native_rendering", false, true);
|
||||||
|
|
||||||
|
|
||||||
// this value string is synchronized with settings_pref.xml preference name
|
// this value string is synchronized with settings_pref.xml preference name
|
||||||
|
|
|
@ -230,8 +230,6 @@ public class MapRenderRepositories {
|
||||||
double cLeftLongitude = dataBox.left;
|
double cLeftLongitude = dataBox.left;
|
||||||
double cRightLongitude = dataBox.right;
|
double cRightLongitude = dataBox.right;
|
||||||
|
|
||||||
log.info(String.format("BLat=%s, TLat=%s, LLong=%s, RLong=%s, zoom=%s", //$NON-NLS-1$
|
|
||||||
cBottomLatitude, cTopLatitude, cLeftLongitude, cRightLongitude, zoom));
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
@ -334,7 +332,12 @@ public class MapRenderRepositories {
|
||||||
|
|
||||||
List<MultyPolygon> pMulti = proccessMultiPolygons(multiPolygons, leftX, rightX, bottomY, topY, zoom);
|
List<MultyPolygon> pMulti = proccessMultiPolygons(multiPolygons, leftX, rightX, bottomY, topY, zoom);
|
||||||
tempList.addAll(pMulti);
|
tempList.addAll(pMulti);
|
||||||
|
if (count > 0) {
|
||||||
|
log.info(String.format("BLat=%s, TLat=%s, LLong=%s, RLong=%s, zoom=%s", //$NON-NLS-1$
|
||||||
|
cBottomLatitude, cTopLatitude, cLeftLongitude, cRightLongitude, zoom));
|
||||||
log.info(String.format("Search done in %s ms. %s results were found.", System.currentTimeMillis() - now, count)); //$NON-NLS-1$
|
log.info(String.format("Search done in %s ms. %s results were found.", System.currentTimeMillis() - now, count)); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cObjects = tempList;
|
cObjects = tempList;
|
||||||
cObjectsBox = dataBox;
|
cObjectsBox = dataBox;
|
||||||
|
@ -450,6 +453,9 @@ public class MapRenderRepositories {
|
||||||
String renderingDebugInfo = currentRenderingContext.renderingDebugInfo;
|
String renderingDebugInfo = currentRenderingContext.renderingDebugInfo;
|
||||||
currentRenderingContext.ended = true;
|
currentRenderingContext.ended = true;
|
||||||
if (checkWhetherInterrupted()) {
|
if (checkWhetherInterrupted()) {
|
||||||
|
// revert if it was interrupted
|
||||||
|
this.bmp = this.prevBmp;
|
||||||
|
this.bmpLocation = this.prevBmpLocation;
|
||||||
currentRenderingContext = null;
|
currentRenderingContext = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -464,6 +470,7 @@ public class MapRenderRepositories {
|
||||||
timeInfo += "\n" + renderingDebugInfo;
|
timeInfo += "\n" + renderingDebugInfo;
|
||||||
}
|
}
|
||||||
final String msg = timeInfo;
|
final String msg = timeInfo;
|
||||||
|
log.info(msg);
|
||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
Loading…
Reference in a new issue