On Thu, 3 Nov 2011, Oliver Eichler wrote:
* Skip making it an option. The benefits are good enough to have it
permanently on. And I doubt that 99% of the users know what it does, how
it works and why to use this option anyway.
ok, we just have to find a good value for ε then. I'll keep it in
QSettings for the time being and just remove it from the UI, ok?
Hm, ok. In a year we will wonder what this peculiar value is good for :)
After a second thought I decided *not* to keep it in QSettings. Why
pollute everybodies preferences file with undocumented parameters anyway?
After all, we have to find a sane default nevertheless.
It's hardcoded to 1.9 in CMapTDB.cpp now.
* But switch it off for closer zoom levels. Map contributor will get a
heart attack if they do not see their polyline as defined. On closer
views the speed up is not noticeable anyway.
ok, although in principle this should not be necessary, as ε is
expressed in pixel units anyway. Where do the closer zoom levels begin?
I would say at zoomFactor <= 2.0 because at this zoom factor the map
resolution gets 24 bit which is the highest one.
Hm, at that zoomFactor speed is definitely an issue on low-end hardware
at least. It's disabled for zoomFactor <= 1.0 now.
* Get rid of that class in a method. :) That is ugly. And it only
defines a single method anyway.
Well, it defines a local function, something that isn't allowed in C++.
I don't think it's *that* ugly, but I'll remove it ;-)
A good old trusty private method is well enough :)
done ;-)
Regards,
Michael
--
message composed with
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Sep 16 2011 22:53:43)
diff --git a/src/CMap3D.cpp b/src/CMap3D.cpp
index 11416b2..dddcdc9 100644
--- a/src/CMap3D.cpp
+++ b/src/CMap3D.cpp
@@ -34,7 +34,11 @@
#include <QtGui>
#include <QtOpenGL>
#include <math.h>
+#if defined(Q_WS_MAC)
+#include <OpenGL/glu.h>
+#else
#include <GL/glu.h>
+#endif
#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
diff --git a/src/CMapTDB.cpp b/src/CMapTDB.cpp
index a438b9a..7228a88 100644
--- a/src/CMapTDB.cpp
+++ b/src/CMapTDB.cpp
@@ -40,6 +40,8 @@
#include <QSqlDatabase>
#include <algorithm>
+#include <QElapsedTimer>
+
//#include <sys/time.h>
#ifdef WIN32
@@ -54,6 +56,9 @@
#undef DEBUG_SHOW_SECTION_BORDERS
#define DEBUG_SHOW_MAPLEVELS
+#define POLYLINE_SIMPLIFICATION_THRESHOLD 1.0
+#define STREETNAME_THRESHOLD 5.0
+
#define TEXTWIDTH 300
CMapTDB::scale_t CMapTDB::scales[] =
@@ -442,30 +447,11 @@ CMapTDB::~CMapTDB()
if(pjsrc) pj_free(pjsrc);
- if(checkPoiLabels)
- {
- delete checkPoiLabels;
- }
-
- if(checkNightView)
- {
- delete checkNightView;
- }
-
- if(comboDetails)
- {
- delete comboDetails;
- }
-
- if(comboLanguages)
- {
- delete comboLanguages;
- }
-
- if(comboTypfiles)
- {
- delete comboTypfiles;
- }
+ delete checkPoiLabels;
+ delete checkNightView;
+ delete comboDetails;
+ delete comboLanguages;
+ delete comboTypfiles;
qDebug() << "CMapTDB::~CMapTDB()";
}
@@ -1934,6 +1920,104 @@ void CMapTDB::draw(QPainter& p)
}
+void CMapTDB::simplifyPolyline(QPolygonF & line) const
+{
+ // disable polyline simplification for closer zoom levels
+ if (zoomFactor >= POLYLINE_SIMPLIFICATION_THRESHOLD)
+ {
+ simplifyPolyline(line.begin(), line.end());
+ line.resize(std::unique(line.begin(), line.end()) - line.begin());
+ }
+}
+
+
+void CMapTDB::simplifyPolyline(QPolygonF::iterator begin, QPolygonF::iterator
end) const
+{
+ if (std::distance(begin, end) > 2)
+ {
+ const QPointF & p1 = *begin++;
+ const QPointF & p2 = *--end;
+
+ double dist, max_dist = 0.0;
+ QPolygonF::iterator pos, max_pos = end;
+
+ if (p2.x() == p1.x())
+ {
+ double min_y = std::min(p1.y(), p2.y());
+ double max_y = std::max(p1.y(), p2.y());
+
+ for (pos = begin; pos != end; pos++)
+ {
+ const QPointF & p = *pos;
+
+ if (p.y() < min_y)
+ {
+ dist = sqrt((p1.x() - p.x()) * (p1.x() - p.x()) + (min_y -
p.y()) * (min_y - p.y()));
+ }
+ else if (p.y() > max_y)
+ {
+ dist = sqrt((p1.x() - p.x()) * (p1.x() - p.x()) + (max_y -
p.y()) * (max_y - p.y()));
+ }
+ else
+ {
+ dist = abs(p.x() - p1.x());
+ }
+
+ if (dist > max_dist)
+ {
+ max_pos = pos;
+ max_dist = dist;
+ }
+ }
+ }
+ else
+ {
+ double m = (p2.y() - p1.y()) / (p2.x() - p1.x());
+ double n = -1.0 / m;
+ double c = p1.y() - m * p1.x();
+
+ double min_x = std::min(p1.x(), p2.x());
+ double max_x = std::max(p1.x(), p2.x());
+
+ for (pos = begin; pos != end; pos++)
+ {
+ const QPointF & p = *pos;
+
+ double d = p.y() - n * p.x();
+ double x = (c - d) / (n - m);
+
+ if (x >= min_x && x <= max_x)
+ {
+ double y = m * x + c;
+ dist = sqrt((p.x() - x) * (p.x() - x) + (p.y() - y) *
(p.y() - y));
+ }
+ else
+ {
+ dist = std::min(sqrt((p1.x() - p.x()) * (p1.x() - p.x()) +
(p1.y() - p.y()) * (p1.y() - p.y())),
+ sqrt((p2.x() - p.x()) * (p2.x() - p.x()) +
(p2.y() - p.y()) * (p2.y() - p.y())));
+ }
+
+ if (dist > max_dist)
+ {
+ max_pos = pos;
+ max_dist = dist;
+ }
+ }
+ }
+
+ if (max_dist >= CResources::self().polylineSimplificationEpsilon())
+ {
+ simplifyPolyline(max_pos, end);
+ simplifyPolyline(begin, max_pos + 1);
+ }
+ else
+ {
+ std::fill(begin, end, p1);
+ }
+ }
+}
+
+
void CMapTDB::draw(const QSize& s, bool needsRedraw, QPainter& p)
{
int i;
@@ -1989,6 +2073,7 @@ void CMapTDB::draw()
fm = QFontMetrics(f);
USE_ANTI_ALIASING(p,!doFastDraw && CResources::self().useAntiAliasing());
+
p.setFont(f);
p.setPen(Qt::black);
p.setBrush(Qt::NoBrush);
@@ -2057,13 +2142,20 @@ void CMapTDB::draw()
if(!doFastDraw)
{
+ QElapsedTimer et;
QVector<QRect> rectPois;
+ et.start();
drawPolylines(p, polylines);
+ qDebug() << "drawPolylines: " << et.restart() << "ms";
drawPoints(p, points, rectPois);
+ qDebug() << "drawPoints: " << et.restart() << "ms";
drawPois(p, pois, rectPois);
+ qDebug() << "drawPois: " << et.restart() << "ms";
drawText(p);
+ qDebug() << "drawText: " << et.restart() << "ms";
drawLabels(p, labels);
+ qDebug() << "drawLabels: " << et.restart() << "ms";
}
@@ -2076,7 +2168,6 @@ void CMapTDB::draw()
}
-#define STREETNAME_THRESHOLD 5.0
void CMapTDB::drawLine(QPainter& p, CGarminPolygon& l, const
IGarminTyp::polyline_property& property, const QFontMetricsF& metrics, const
QFont& font)
{
double * u = l.u.data();
@@ -2099,6 +2190,8 @@ void CMapTDB::drawLine(QPainter& p, CGarminPolygon& l,
const IGarminTyp::polylin
line.append(QPointF(*u++, *v++));
}
+ simplifyPolyline(line);
+
if (zoomFactor < STREETNAME_THRESHOLD && property.labelType !=
IGarminTyp::eNone)
{
collectText(l, line, font, metrics, lineWidth);
@@ -2127,6 +2220,8 @@ void CMapTDB::drawLine(QPainter& p, const CGarminPolygon&
l)
line.append(QPointF(*u++, *v++));
}
+ simplifyPolyline(line);
+
p.drawPolyline(line);
}
@@ -2179,6 +2274,8 @@ void CMapTDB::drawPolylines(QPainter& p, polytype_t&
lines)
int pixmapCount = 0;
int borderCount = 0;
int normalCount = 0;
+ int imageCount = 0;
+ int deletedCount = 0;
QHash<quint32, QList<quint32> > dict;
for(int i = 0; i < lines.count(); ++i)
@@ -2211,9 +2308,9 @@ void CMapTDB::drawPolylines(QPainter& p, polytype_t&
lines)
pixmapCount++;
- double * u = item.u.data();
- double * v = item.v.data();
- const int size = item.u.size();
+ double * u = item.u.data();
+ double * v = item.v.data();
+ int size = item.u.size();
if(size < 2)
{
@@ -2222,27 +2319,36 @@ void CMapTDB::drawPolylines(QPainter& p, polytype_t&
lines)
convertRad2Pt(u,v,size);
+ int i;
+
line.resize(0);
line.reserve(size);
lengths.resize(0);
+
+ for(i = 0; i < size; ++i)
+ {
+ line.append(QPointF(u[i], v[i]));
+ }
+
+ deletedCount += line.size();
+ simplifyPolyline(line);
+ deletedCount -= line.size();
+ size = line.size();
+
lengths.reserve(size);
double u1, u2, v1, v2;
QPainterPath path;
double segLength, totalLength = 0;
- int i;
- u1 = u[0];
- v1 = v[0];
- line.append(QPointF(u1,v1));
+ u1 = line[0].x();
+ v1 = line[0].y();
for(i = 1; i < size; ++i)
{
- u2 = u[i];
- v2 = v[i];
-
- line.append(QPointF(u2,v2));
+ u2 = line[i].x();
+ v2 = line[i].y();
segLength = sqrt((u2 - u1) * (u2 - u1) + (v2 - v1)
* (v2 - v1));
totalLength += segLength;
@@ -2299,6 +2405,7 @@ void CMapTDB::drawPolylines(QPainter& p, polytype_t&
lines)
}
#else
p.drawImage(0,-h/2, img2line(pixmap, segLength));
+ imageCount++;
#endif
p.restore();
@@ -2343,7 +2450,11 @@ void CMapTDB::drawPolylines(QPainter& p, polytype_t&
lines)
}
}
- // fprintf(stderr, "pixmapCount: %d, borderCount: %d, normalCount:
%d\n", pixmapCount, borderCount, normalCount);
+ qDebug() << "pixmapCount:" << pixmapCount
+ << "borderCount:" << borderCount
+ << "normalCount:" << normalCount
+ << "imageCount:" << imageCount
+ << "deletedCount:" << deletedCount;
}
@@ -2685,7 +2796,6 @@ inline bool isCluttered(QVector<QRect>& rectPois, const
QRect& rect)
void CMapTDB::drawPoints(QPainter& p, pointtype_t& pts, QVector<QRect>&
rectPois)
{
-
pointtype_t::iterator pt = pts.begin();
while(pt != pts.end())
{
@@ -2753,6 +2863,9 @@ void CMapTDB::drawPois(QPainter& p, pointtype_t& pts,
QVector<QRect>& rectPois)
IGarminTyp::label_type_e labelType = IGarminTyp::eStandard;
bool showLabel = true;
+ QPixmap blueBullet(":/icons/small_bullet_blue.png");
+ QPixmap redBullet(":/icons/small_bullet_red.png");
+
pointtype_t::iterator pt = pts.begin();
while(pt != pts.end())
{
@@ -2760,7 +2873,7 @@ void CMapTDB::drawPois(QPainter& p, pointtype_t& pts,
QVector<QRect>& rectPois)
if(isCluttered(rectPois, QRect(pt->lon, pt->lat,16,16)))
{
- p.drawPixmap(pt->lon - 4, pt->lat - 4,
QPixmap(":/icons/small_bullet_blue.png"));
+ p.drawPixmap(pt->lon - 4, pt->lat - 4, blueBullet);
++pt;
continue;
}
@@ -2775,7 +2888,7 @@ void CMapTDB::drawPois(QPainter& p, pointtype_t& pts,
QVector<QRect>& rectPois)
}
else
{
- p.drawPixmap(pt->lon - 4, pt->lat - 4,
QPixmap(":/icons/small_bullet_red.png"));
+ p.drawPixmap(pt->lon - 4, pt->lat - 4, redBullet);
}
if(showLabel)
diff --git a/src/CMapTDB.h b/src/CMapTDB.h
index 13a33ed..454c3e8 100644
--- a/src/CMapTDB.h
+++ b/src/CMapTDB.h
@@ -137,6 +137,9 @@ class CMapTDB : public IMap
void drawLine(QPainter& p, CGarminPolygon& l, const
IGarminTyp::polyline_property& property, const QFontMetricsF& metrics, const
QFont& font);
void drawLine(QPainter& p, const CGarminPolygon& l);
+ void simplifyPolyline(QPolygonF & line) const;
+ void simplifyPolyline(QPolygonF::iterator begin, QPolygonF::iterator
end) const;
+
QString createLegendString(const QMap<int,QString>& strings);
#pragma pack(1)
diff --git a/src/CResources.cpp b/src/CResources.cpp
index ad5f30d..ae30b3f 100644
--- a/src/CResources.cpp
+++ b/src/CResources.cpp
@@ -64,6 +64,7 @@ CResources::CResources(QObject * parent)
, m_showZoomLevel(true)
, m_useAntiAliasing(true)
, m_reducePoiIcons(true)
+, m_polylineSimplificationEpsilon(2.5)
, m_WptTextColor(Qt::black)
{
@@ -131,13 +132,15 @@ CResources::CResources(QObject * parent)
unit = new CUnitMetric(this);
}
- m_showTrackProfile =
cfg.value("environment/showTrackProfile",m_showTrackProfile).toBool();
- m_showNorth = cfg.value("environment/showNorth",m_showNorth).toBool();
- m_showScale = cfg.value("environment/showScale",m_showScale).toBool();
- m_showToolTip =
cfg.value("environment/showToolTip",m_showToolTip).toBool();
- m_showZoomLevel =
cfg.value("environment/showZoomLevel",m_showZoomLevel).toBool();
- m_useAntiAliasing =
cfg.value("environment/useAntiAliasing",m_useAntiAliasing).toBool();
- m_reducePoiIcons =
cfg.value("environment/reducePoiIcons",m_reducePoiIcons).toBool();
+ m_showTrackProfile =
cfg.value("environment/showTrackProfile",m_showTrackProfile).toBool();
+ m_showNorth =
cfg.value("environment/showNorth",m_showNorth).toBool();
+ m_showScale =
cfg.value("environment/showScale",m_showScale).toBool();
+ m_showToolTip =
cfg.value("environment/showToolTip",m_showToolTip).toBool();
+ m_showZoomLevel =
cfg.value("environment/showZoomLevel",m_showZoomLevel).toBool();
+ m_useAntiAliasing =
cfg.value("environment/useAntiAliasing",m_useAntiAliasing).toBool();
+ m_reducePoiIcons =
cfg.value("environment/reducePoiIcons",m_reducePoiIcons).toBool();
+
+ m_polylineSimplificationEpsilon =
cfg.value("environment/polylineSimplificationEpsilon",m_polylineSimplificationEpsilon).toDouble();
m_WptTextColor = QColor(cfg.value("environment/wptTextColor",
m_WptTextColor.name()).toString());
@@ -203,6 +206,7 @@ CResources::~CResources()
cfg.setValue("environment/showZoomLevel",m_showZoomLevel);
cfg.setValue("environment/useAntiAliasing",m_useAntiAliasing);
cfg.setValue("environment/reducePoiIcons",m_reducePoiIcons);
+
cfg.setValue("environment/polylineSimplificationEpsilon",m_polylineSimplificationEpsilon);
cfg.setValue("environment/wptTextColor", m_WptTextColor.name());
}
diff --git a/src/CResources.h b/src/CResources.h
index e25cd1b..ba5bde6 100644
--- a/src/CResources.h
+++ b/src/CResources.h
@@ -72,6 +72,7 @@ class CResources : public QObject
bool playSound(){return m_playSound;}
bool useAntiAliasing(){return m_useAntiAliasing;}
bool reducePoiIcons(){return m_reducePoiIcons;}
+ double polylineSimplificationEpsilon(){return
m_polylineSimplificationEpsilon;}
QColor wptTextColor(){return m_WptTextColor;}
@@ -145,6 +146,7 @@ class CResources : public QObject
bool m_showZoomLevel;
bool m_useAntiAliasing;
bool m_reducePoiIcons;
+ double m_polylineSimplificationEpsilon;
QColor m_WptTextColor;
------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
Qlandkartegt-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/qlandkartegt-users