[installation] Init with inital config for global

This commit is contained in:
2025-10-30 15:08:17 +01:00
commit 7640b452ed
3678 changed files with 2200095 additions and 0 deletions

View File

@ -0,0 +1,65 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_ANNOTATION_LAYER_H__
#define SEISCOMP_GUI_MAP_LAYERS_ANNOTATION_LAYER_H__
#include <seiscomp/gui/map/annotations.h>
#include <seiscomp/gui/map/layer.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class AnnotationLayer : public Layer {
public:
AnnotationLayer(QObject* parent = nullptr,
Annotations *annotations = nullptr);
void setAnnotations(Annotations *annotations) {
_annotations = annotations;
}
Annotations *annotations() const {
return _annotations;
}
void draw(const Seiscomp::Gui::Map::Canvas*, QPainter &painter);
private:
typedef QList<QRect> Row;
typedef QVector<Row> Grid;
Annotations *_annotations;
};
} // ns Map
} // ns Gui
} // ns Seiscomp
#endif

View File

@ -0,0 +1,173 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_ANNOTATIONS_H
#define SEISCOMP_GUI_MAP_ANNOTATIONS_H
#include <QColor>
#include <QFont>
#include <QPen>
#include <QPoint>
#include <QString>
#include <QVariant>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Annotations;
class AnnotationItem;
struct AnnotationStyle : public QObject {
AnnotationStyle(QObject *parent = nullptr);
virtual ~AnnotationStyle() {}
virtual void draw(QPainter &painter, const AnnotationItem &item);
virtual QRect itemRect(QPainter &painter, const AnnotationItem &item,
const QPoint &pos) const;
struct Palette {
QPen textPen;
QPen borderPen;
QBrush brush;
};
// One for normal (0) and one for highlighted (1)
Palette palette[2];
QFont font;
};
/**
* @brief The AnnotationItem struct holds properties like text, text color etc.
* which might be used when rendering an item on a map.
*/
class AnnotationItem {
private:
AnnotationItem(Annotations *parent) : pool(parent) {}
AnnotationItem(Annotations *parent, const QString &text)
: pool(parent), text(text) {}
public:
~AnnotationItem();
public:
/**
* @brief Updates the label rect of the item based on the given position
* and style
* @param pos The position of the label rect
*/
void updateLabelRect(QPainter &painter, const QPoint &pos) {
if ( style ) {
labelRect = style->itemRect(painter, *this, pos);
}
else {
labelRect = QRect();
}
}
public:
Annotations *pool{nullptr};
QString text;
AnnotationStyle *style{nullptr};
bool visible{true};
bool highlighted{false};
QRect labelRect;
QVariant data;
friend class Annotations;
};
class Annotations : public QObject {
public:
typedef QList<AnnotationItem*> Items;
typedef Items::const_iterator const_iterator;
public:
Annotations(QObject *parent = nullptr);
~Annotations();
const_iterator begin() const {
return _items.begin();
}
const_iterator end() const {
return _items.end();
}
/**
* @brief Clears the annotation pool
* This call calls delete for each AnnotationItem.
*/
void clear();
int size() { return _items.size(); }
/**
* @brief Adds a new object to the annotation pool
* @param text The annotation text
* @return Link to an annotation item which is owned by this instance
*/
AnnotationItem *add(const QString &text);
/**
* @brief Removes annotation item from annotation pool and deletes it
* @param item The annotation item to remove
* @return true if removed, false otherwise
*/
bool remove(const AnnotationItem *item);
/**
* @brief Removes annotation item from annotation pool but does not delete
* it. The pool member in the item will be set to nullptr.
* @param item The annotation item to be taken
* @return true if taken, false otherwise
*/
bool take(const AnnotationItem *item);
/**
* @brief Sets the default annotation style used while
* creating annotation items
* @param style The annotation style to set
*/
void setDefaultStyle(AnnotationStyle *style) {
_style = style;
}
private:
Items _items;
AnnotationStyle _defaultStyle;
AnnotationStyle *_style{nullptr};
};
} // ns Map
} // ns Gui
} // ns Seiscomp
#endif

View File

@ -0,0 +1,495 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_CANVAS_H
#define SEISCOMP_GUI_MAP_CANVAS_H
#ifndef Q_MOC_RUN
#include <seiscomp/gui/core/maps.h>
#include <seiscomp/gui/map/projection.h>
#include <seiscomp/gui/map/legend.h>
#include <seiscomp/gui/map/imagetree.h>
#include <seiscomp/gui/map/layers/citieslayer.h>
#include <seiscomp/gui/map/layers/gridlayer.h>
#include <seiscomp/gui/map/layers/geofeaturelayer.h>
#include <seiscomp/gui/map/layers/symbollayer.h>
#include <seiscomp/math/coord.h>
#include <seiscomp/geo/feature.h>
#include <seiscomp/utils/timer.h>
#endif
#include <QHash>
#include <QObject>
#include <QPolygon>
class QMouseEvent;
class QMenu;
namespace Seiscomp {
namespace Gui {
namespace Map {
class Layer;
DEFINE_SMARTPOINTER(TextureCache);
// For backward compatibility
typedef SymbolLayer SymbolCollection;
class SC_GUI_API Canvas : public QObject {
Q_OBJECT
public:
Canvas(const MapsDesc &);
Canvas(ImageTree *mapTree);
~Canvas();
public:
void setFont(QFont f);
QFont font() const { return _font; }
void setBackgroundColor(QColor c);
bool setProjectionByName(const char *name);
const std::string &projectionName() const { return _projectionName; }
void setSize(int w, int h);
QSize size() const { return _buffer.size(); }
int width() const { return _buffer.width(); }
int height() const { return _buffer.height(); }
/**
* @brief Sets the margin of the legend area with respect to the
* canvas border. The default value is 10 pixels. This methods
* was added with API 11.
* @param margin The margin in pixels.
*/
void setLegendMargin(int margin);
/**
* @brief Returns the margin of the legend area with respect to the
* canvas border. This methods was added with API 11.
* @return The margin in pixels
*/
int legendMargin() const { return _margin; }
void setGrayScale(bool);
bool isGrayScale() const;
/**
* @brief Sets bilinear filtering for map tile interpolation. This is
* only used if not in preview mode.
* @param enable Boolean flag
*/
void setBilinearFilter(bool enable);
/**
* @brief Enables the preview mode. The preview mode is meant to be
* used for fast rendering the map, e.g. with antialiasing
* switched of. This is mainly used while dragging the map.
* @param enable Boolean flag
*/
void setPreviewMode(bool enable);
/**
* @brief Returns whether the canvas rendering is currently in preview
* mode or not.
* @return A boolean flag
*/
bool previewMode() const;
void setDrawGrid(bool);
bool isDrawGridEnabled() const;
void setDrawLayers(bool);
bool isDrawLayersEnabled() const;
void setDrawCities(bool);
bool isDrawCitiesEnabled() const;
bool isDrawLegendsEnabled() const;
void setImageFilter(bool);
bool isImageFilterEnabled() const;
bool displayRect(const QRectF& rect);
void setMapCenter(QPointF c);
const QPointF& mapCenter() const;
bool setZoomLevel(float);
float zoomLevel() const;
float pixelPerDegree() const;
void setView(QPoint c, float zoom);
void setView(QPointF c, float zoom);
/**
* @brief Sets the minimum pixel distance of two adjacent vertices
* to be rendered as a line when rendering GeoFeatures and polylines.
* Or in other words, if the pixel distance of two adjacent vertices is
* less than the given distance, both vertices collapse into a single
* vertex. The greater the distance the less details the rendered shape
* will have.
* @param pixel The distance in pixels
*/
void setPolygonRoughness(uint pixel);
uint polygonRoughness() const;
/**
* @brief Sets the polygon clip hint.
*
* The hint might or might not be interpreted by projections. If the
* clipHint is DoClip then polygons are clipped against the viewport
* before rendering them. This will reduce the number of vertices
* significantly but also increases processing time. The default
* is DoClip.
* @param hint The clipping hint
*/
void setPolygonClipHint(ClipHint hint);
ClipHint polygonClipHint() const;
Map::Projection *projection() const { return _projection; }
bool isVisible(double lon, double lat) const;
void setSelectedCity(const Math::Geo::CityD*);
//! Draws a geometric line (great circle) given in geographical coordinates (lon, lat)
//! Returns the distance in degree of the line
double drawLine(QPainter &painter, const QPointF &start, const QPointF &end) const;
//! Draws a polyline in geographical coordinates (lon, lat).
//! Returns number of line segments drawn.
//! Does not check for clipping
size_t drawPolyline(QPainter &painter, size_t n, const Geo::GeoCoordinate *line,
bool isClosedPolygon, bool interpolate = false,
int roughness = -1) const;
//! Does not check for clipping
size_t drawPolygon(QPainter &painter, size_t n, const Geo::GeoCoordinate *line,
bool isClosedPolygon = true, int roughness = -1,
ClipHint clipHint = DoClip) const;
//! Draws a GeoFeature as either polyline or filled polygon and
//! checks for clipping
size_t drawFeature(QPainter &painter, const Geo::GeoFeature *feature,
bool filled = false, int roughness = -1,
ClipHint clipHint = DoClip) const;
/**
* @brief Draws an image onto the current map buffer. If this function
* is called *after* @drawImageLayer then it does not have an
* effect because the map buffer has been rendered already onto
* the painter device.
* @param geoReference The geo reference of the image.
* @param image The image to be rendered.
* @param compositionMode The composition mode which will be used to
* combine the current base layer (tiles) with
* the image.
* @param filterMode The filter mode used to render the image.
*/
void drawImage(const QRectF &geoReference, const QImage &image,
CompositionMode compositionMode = CompositionMode_Default,
FilterMode filterMode = FilterMode_Auto);
void draw(QPainter &p);
void centerMap(const QPoint &centerPnt);
void translate(const QPoint &delta);
void translate(const QPointF &delta);
void drawImageLayer(QPainter &painter);
void drawVectorLayer(QPainter &painter);
void drawLayers(QPainter &painter);
void updateBuffer();
void setBuffer(QImage buffer) { _buffer = buffer; }
QImage &buffer() { return _buffer; }
//! Returns the number of layers
int layerCount() const { return _layers.count(); }
//! Returns the i-th layer if the index is valid
Layer* layer(int i) const {
if ( i < 0 || i >= _layers.count() ) return nullptr;
return _layers[i];
}
//! Canvas does take ownership of layer if the layer does not
//! have a parent at the time of appending or prepending.
bool prependLayer(Layer*);
bool addLayer(Layer*);
bool insertLayerBefore(const Layer*, Layer*);
void removeLayer(Layer*);
void lower(Layer*);
void raise(Layer*);
Layer *hoverLayer() const;
bool filterContextMenuEvent(QContextMenuEvent*, QWidget*);
bool filterKeyPressEvent(QKeyEvent *event);
bool filterKeyReleaseEvent(QKeyEvent *event);
bool filterMouseMoveEvent(QMouseEvent*);
bool filterMousePressEvent(QMouseEvent*);
bool filterMouseReleaseEvent(QMouseEvent*);
bool filterMouseDoubleClickEvent(QMouseEvent*);
QMenu* menu(QMenu*) const;
//! Returns whether the rendering is complete or if there are
//! still some updates in the pipeline that updated later. If this
//! function return false, the signal renderingCompleted() is emitted
//! once it is done.
//! This function was introduced in API 1.1.
bool renderingComplete() const;
public:
GridLayer *gridLayer();
const GridLayer *gridLayer() const;
CitiesLayer *citiesLayer();
const CitiesLayer *citiesLayer() const;
GeoFeatureLayer *geoFeatureLayer();
const GeoFeatureLayer *geoFeatureLayer() const;
SymbolLayer *symbolCollection();
const SymbolLayer *symbolCollection() const;
public slots:
//! Reloads all tiles and empties the texture cache
//! This slot was introduced in API 1.1.
void reload();
//! This slot was added in API 11
void setDrawLegends(bool);
//! This slot was added in API 11
void showLegends();
//! This slot was added in API 11
void hideLegends();
/**
* @brief Enables/disables legend stacking.
*
* If legend stacking is enabled then two toggle buttons will be
* rendered in the legends title bar to swap the visible legend. If
* stacking is disabled then all legends of a particular edge will
* be rendered next to each other. This slot was added in API 11.
*/
void setLegendStacking(bool);
void bringToFront(Seiscomp::Gui::Map::Legend*);
void setLegendEnabled(Seiscomp::Gui::Map::Legend*, bool);
/**
* @brief This handler is called when a new legend is
* added to a layer.
* This slot was introduced with API XX
* @param legend The legend
*/
void onLegendAdded(Legend *legend);
/**
* @brief This handler is called when a legend is removed
* from a layer.
* This slot was introduced with API XX
* @param legend
*/
void onLegendRemoved(Legend *legend);
signals:
//! This signal is emitted if draw() caused asynchronous data requests
//! and when those requests are finished.
//! This signal was introduced with API 1.1.
void renderingCompleted();
void bufferUpdated();
void projectionChanged(Seiscomp::Gui::Map::Projection*);
void legendVisibilityChanged(bool);
void updateRequested();
void customLayer(QPainter*);
private:
void init();
void drawCity(QPainter &painter, const Math::Geo::CityD &,
QVector< QList<QRect> > &grid,
QFont &font, QFontMetrics &fontMetrics,
int rowHeight,
bool &lastUnderline, bool &lastBold);
void drawLegends(QPainter &painter);
void setupLayer(Layer *layer);
private slots:
void updatedTiles();
void completeTiles();
void updateLayer(const Layer::UpdateHints&);
private:
struct LegendItem {
LegendItem() : legend(0), dirty(true) {}
LegendItem(Legend *legend) : legend(legend), dirty(true) {}
Legend *legend;
bool dirty;
};
typedef QVector<LegendItem> Legends;
struct LegendArea : public Legends {
LegendArea() : currentIndex(-1) {}
int find(Legend *legend) const {
for ( int i = 0; i < count(); ++i ) {
if ( at(i).legend == legend )
return i;
}
return -1;
}
bool hasIndex(int index) {
return ( index >= 0 && index < count() );
}
bool mousePressEvent(QMouseEvent *e);
bool mouseReleaseEvent(QMouseEvent *e);
int findNext(bool forward = true) const;
QRect header;
QRect decorationRects[2];
int currentIndex;
};
typedef QHash<Qt::Alignment, LegendArea> LegendAreas;
typedef QList<Layer*> Layers;
typedef QList<LayerPtr> CustomLayers;
private:
QFont _font;
Projection* _projection;
ImageTreePtr _maptree;
std::string _projectionName;
QImage _buffer;
QColor _backgroundColor{Qt::lightGray};
uint _polygonRoughness;
double _maxZoom;
QPointF _center;
float _zoomLevel{1.0f};
bool _grayScale{false};
bool _filterMap;
bool _dirtyRasterLayer{true};
bool _dirtyVectorLayers{true};
bool _previewMode{false};
bool _stackLegends{true};
Layers _layers;
Layer *_hoverLayer{nullptr};
CustomLayers _customLayers;
CitiesLayer _citiesLayer;
GridLayer _gridLayer;
GeoFeatureLayer _geoFeatureLayer;
SymbolLayer _symbolLayer;
LegendAreas _legendAreas;
int _margin{10};
bool _isDrawLegendsEnabled{true};
Util::StopWatch _tileUpdateTimer;
};
inline bool Canvas::previewMode() const {
return _previewMode;
}
inline Layer *Canvas::hoverLayer() const {
return _hoverLayer;
}
inline GridLayer *Canvas::gridLayer() {
return &_gridLayer;
}
inline const GridLayer *Canvas::gridLayer() const {
return &_gridLayer;
}
inline CitiesLayer *Canvas::citiesLayer() {
return &_citiesLayer;
}
inline const CitiesLayer *Canvas::citiesLayer() const {
return &_citiesLayer;
}
inline GeoFeatureLayer *Canvas::geoFeatureLayer() {
return &_geoFeatureLayer;
}
inline const GeoFeatureLayer *Canvas::geoFeatureLayer() const {
return &_geoFeatureLayer;
}
inline SymbolLayer *Canvas::symbolCollection() {
return &_symbolLayer;
}
inline const SymbolLayer *Canvas::symbolCollection() const {
return &_symbolLayer;
}
inline uint Canvas::polygonRoughness() const {
return _polygonRoughness;
}
inline void Canvas::setPolygonRoughness(uint pixel) {
_polygonRoughness = pixel;
}
}
}
}
#endif

View File

@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_CITIESLAYER_H
#define SEISCOMP_GUI_MAP_LAYERS_CITIESLAYER_H
#include <seiscomp/gui/qt.h>
#include <seiscomp/gui/map/layer.h>
#include <seiscomp/math/coord.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class Projection;
class SC_GUI_API CitiesLayer : public Layer {
public:
CitiesLayer(QObject* = nullptr);
virtual ~CitiesLayer();
virtual void init(const Config::Config&);
virtual void draw(const Canvas*, QPainter&);
void setSelectedCity(const Math::Geo::CityD*);
const Math::Geo::CityD* selectedCity() const;
private:
typedef QList<QRect> Row;
typedef QVector<Row> Grid;
private:
bool drawCity(QPainter&, Grid&, QFont&, bool&, bool&,
const Projection*, const Math::Geo::CityD&,
const QFontMetrics&, int, int);
private:
const Math::Geo::CityD *_selectedCity;
int _topPopulatedPlaces;
};
} // namespace Map
} // namespce Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,104 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_DECORATOR_H
#define SEISCOMP_GUI_DECORATOR_H
#include <memory>
#include <QPainter>
#include <seiscomp/gui/qt.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
/** \class Decorator
*
* Abstract class to decorate a Symbol derived class. When a derived decorator is
* passed to a symbol the map and baseObject member are automatically set by the
* respective symbol. The same is true for all other (nested) decorator which are
* associated whith the passed decorator. Therefore the user is obliged to assure
* that the other decorator operate on the same type of datamodel object (pick, origin...)
*/
class SC_GUI_API Decorator {
// ------------------------------------------------------------------
// X'struction
// ------------------------------------------------------------------
public:
Decorator(Decorator* decorator = nullptr)
: _decorator(decorator),
_visible(true) {
}
virtual ~Decorator() {}
// ------------------------------------------------------------------
// Public Interface
// ------------------------------------------------------------------
public:
void draw(const Canvas *canvas, QPainter &painter) {
if ( _decorator.get() )
_decorator->draw(canvas, painter);
customDraw(canvas, painter);
}
void setVisible(bool visible) {
if ( _decorator.get() )
_decorator->setVisible(visible);
_visible = visible;
}
bool isVisible() const {
return _visible;
}
// ------------------------------------------------------------------
// Protected Interface
// ------------------------------------------------------------------
protected:
virtual void customDraw(const Canvas *canvas, QPainter &painter) = 0;
// ------------------------------------------------------------------
// Private Members
// ------------------------------------------------------------------
private:
std::unique_ptr<Decorator> _decorator;
bool _visible;
};
} // namespace Map
} // namespace Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,202 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_GEOFEATURELAYER_H
#define SEISCOMP_GUI_MAP_LAYERS_GEOFEATURELAYER_H
#include <seiscomp/gui/map/layer.h>
#ifndef Q_MOC_RUN
#include <seiscomp/geo/featureset.h>
#include <seiscomp/geo/index/quadtree.h>
#endif
#include <QImage>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class SC_GUI_API GeoFeatureLayer : public Layer,
virtual public Geo::GeoFeatureSetObserver {
Q_OBJECT
public:
GeoFeatureLayer(QObject *parent = nullptr);
virtual ~GeoFeatureLayer();
public:
/**
* @brief Returns a feature under the given coordinate.
* @param coord The coordinate.
* @return A pointer to the feature instance or nullptr. Do not delete
* the feature, its ownership is still at the global
* GeoFeatureSet.
*/
const Geo::GeoFeature *findFeature(const Geo::GeoCoordinate &coord) const;
/**
* @brief Convenience function for @findFeature(const Geo::GeoCoordinate &coord).
* @param lat The latitude of the coordinate
* @param lon The longitude of the coordinate
* @return See @findFeature(const Geo::GeoCoordinate &coord).
*/
const Geo::GeoFeature *findFeature(qreal lat, qreal lon) const;
/**
* @brief Renders the geofeatures on a given canvas with a given
* painter. This function is called from bufferUpdated.
* @param canvas The target canvas
* @param painter The painter to paint with
*/
void renderFeatures(Canvas *canvas, QPainter &painter);
virtual void setVisible(bool flag);
virtual void bufferUpdated(Canvas *canvas, QPainter &painter);
virtual QMenu *menu(QMenu*) const;
virtual void geoFeatureSetUpdated();
private slots:
void toggleFeatureVisibility(bool);
void disableFeatureVisibility();
void showFeatures();
void hideFeatures();
void reloadFeatures();
private:
void initLayerProperites();
private:
struct SC_GUI_API LayerProperties {
enum SymbolShape {
Disabled,
None,
Circle,
Triangle,
Square,
Diamond
};
const LayerProperties *parent{nullptr};
std::string name;
std::string title;
Qt::Orientation orientation{Qt::Vertical};
Qt::Alignment legendArea{Qt::AlignTop | Qt::AlignLeft};
QPainter::CompositionMode compositionMode{QPainter::CompositionMode_SourceOver};
std::string label;
int index{0};
bool visible{true};
QPen pen;
QBrush brush;
QFont font;
bool drawName{false};
bool debug{false};
int rank{-1};
int roughness{-1};
bool filled{false};
int symbolSize{8};
QImage symbolIcon;
QPoint symbolIconHotspot;
SymbolShape symbolShape{Disabled};
QPolygon symbolPolygon;
Qt::Alignment symbolNameAlignment{Qt::AlignTop | Qt::AlignHCenter};
int symbolNameMargin{3};
// derived members
QRect symbolRect;
LayerProperties(const std::string &name) : name(name) {}
LayerProperties(const std::string &name,
const LayerProperties *parent) {
*this = *parent;
this->name = name;
this->parent = parent;
this->title = std::string(); // Reset the legend title
}
bool isChild(const LayerProperties* child) const;
void read(const std::string &dataDir = "");
static SymbolShape getSymbolShape(const std::string &type);
};
struct CategoryNode {
CategoryNode(const Geo::Category*);
~CategoryNode();
CategoryNode *nodeForCategory(const Geo::Category *cat);
CategoryNode *nodeForProperties(const LayerProperties *props);
const Geo::Category *category;
LayerProperties *properties{nullptr};
std::vector<CategoryNode*> childs;
std::vector<CategoryNode*> childsByName;
Geo::QuadTree quadtree;
Geo::GeoBoundingBox bbox;
};
static bool compareByIndex(const LayerProperties *p1,
const LayerProperties *p2);
static bool compareNodeByIndex(const GeoFeatureLayer::CategoryNode *n1,
const GeoFeatureLayer::CategoryNode *n2);
static bool compareNodeByName(const GeoFeatureLayer::CategoryNode *n1,
const GeoFeatureLayer::CategoryNode *n2);
CategoryNode *createOrGetNodeForCategory(const Geo::Category *cat);
void buildLegends(CategoryNode *node);
QMenu *buildMenu(CategoryNode *node, QMenu *parentMenu) const;
void collectLegendItems(CategoryNode *node, QVector<LayerProperties*> &items);
void orderTree(CategoryNode *node);
void updateBbox(CategoryNode *node);
const Geo::GeoFeature *findFeature(CategoryNode *node,
const Geo::GeoCoordinate &coord) const;
bool toggleVisibility(CategoryNode *node, bool visible);
void drawFeatures(CategoryNode *node, Canvas *canvas,
QPainter &painter, const QPen &debugPen);
bool drawFeature(Canvas *canvas, QPainter *painter,
const QPen *debugPen, const LayerProperties *props,
const Geo::GeoFeature *f);
bool _initialized;
CategoryNode *_root;
};
}
}
}
#endif

View File

@ -0,0 +1,56 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_GRIDLAYER_H
#define SEISCOMP_GUI_MAP_LAYERS_GRIDLAYER_H
#include <seiscomp/gui/qt.h>
#include <seiscomp/gui/map/layer.h>
#include <seiscomp/math/coord.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class SC_GUI_API GridLayer : public Layer {
public:
GridLayer(QObject* = nullptr);
virtual ~GridLayer();
virtual void draw(const Canvas*, QPainter&);
void setGridDistance(const QPointF&);
const QPointF& gridDistance() const;
private:
QPointF _gridDistance;
};
} // namespace Map
} // namespce Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,254 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_IMAGETREE_H
#define SEISCOMP_GUI_MAP_IMAGETREE_H
#ifndef Q_MOC_RUN
#include <seiscomp/core/interfacefactory.h>
#include <seiscomp/core/baseobject.h>
#endif
#include <seiscomp/gui/core/maps.h>
#include <QImage>
namespace Seiscomp {
namespace Gui {
namespace Map {
DEFINE_SMARTPOINTER(TextureCache);
class ImageTree;
struct SC_GUI_API TileIndex {
typedef uint64_t Storage;
enum Traits {
Invalid = uint64_t(-1),
MaxLevel = 29,
LevelBits = 5,
RowBits = MaxLevel,
ColumnBits = MaxLevel
};
Storage id;
TileIndex();
TileIndex(uint8_t level, uint32_t row, uint32_t column);
uint8_t level() const;
uint32_t row() const;
uint32_t column() const;
TileIndex parent() const;
bool operator==(const TileIndex &other) const;
bool operator!=(const TileIndex &other) const;
bool operator<(const TileIndex &other) const;
operator bool() const;
};
std::ostream &operator<<(std::ostream &os, const TileIndex &index);
DEFINE_SMARTPOINTER(TileStore);
class SC_GUI_API TileStore : public Core::BaseObject {
public:
enum LoadResult {
OK,
Deferred,
Error
};
TileStore();
public:
const QSize &tileSize() const { return _tilesize; }
//! Sets the parent image tree that gets notificiations about
//! state changed, e.g. finishedLoading.
void setImageTree(ImageTree *tree);
public:
virtual int maxLevel() const = 0;
//! Opens a tile repository and sets the desc flags accordingly
//! if necessary.
virtual bool open(MapsDesc &desc) = 0;
/**
* @brief Load a tile for a given index.
* Loading can happen synchronously or asynchronously. The later case
* should return the status LoadResult::Deferred and an invalid
* image. If a deferred image could not be loaded by the store it
* should then call invalidate with the failed index.
* @param img The image to be populated.
* @param tile The tile index
* @return Success flag.
*/
virtual LoadResult load(QImage &img, const TileIndex &tile) = 0;
//! Return a unique ID for a node
virtual QString getID(const TileIndex &tile) const = 0;
//! Validate the existance of a tile
virtual bool validate(int level, int column, int row) const = 0;
virtual bool hasPendingRequests() const = 0;
//! Refresh the image store, e.g. invalidate its cache
virtual void refresh() = 0;
protected:
//! Async notification that a tile has been loaded.
void finishedLoading(QImage &img, const TileIndex &tile);
//! Async notification that a tile has been loaded.
void loadingComplete(QImage &img, TileIndex tile);
//! Async notification that loading a tile has been aborted
void loadingCancelled(TileIndex tile);
//! Invalidates the tile of a particular node
void invalidate(const TileIndex &tile);
protected:
ImageTree *_tree;
QSize _tilesize;
};
DEFINE_INTERFACE_FACTORY(TileStore);
#define REGISTER_TILESTORE_INTERFACE(Class, Service) \
Seiscomp::Core::Generic::InterfaceFactory<Seiscomp::Gui::Map::TileStore, Class> __##Class##InterfaceFactory__(Service)
DEFINE_SMARTPOINTER(ImageTree);
class SC_GUI_API ImageTree : public QObject, public Core::BaseObject {
Q_OBJECT
public:
ImageTree(const MapsDesc &desc);
~ImageTree();
public:
bool valid() const { return _store.get(); }
//! This function was introduced in API 1.1
bool hasPendingRequests() const { return _store && _store->hasPendingRequests(); }
//! Returns the currently attached cache instance.
//! If no cache is yet attached a new cache is
//! created and stored in the object.
TextureCache *getCache();
//! Empties the texture cache and tells the store to do a refresh
//! as well.
//! This function was introduced in API 1.1.
void refresh();
public:
void finishedLoading(QImage &img, const TileIndex &tile);
void loadingComplete(QImage &img, TileIndex tile);
void loadingCancelled(TileIndex tile);
void invalidate(const TileIndex &tile);
signals:
void tilesUpdated();
//! Emitted when all tiles are loaded and no asynchronous requests
//! are still pending.
//! This signal was introduced in API 1.1.
void tilesComplete();
protected:
TextureCachePtr _cache;
TileStorePtr _store;
bool _isMercatorProjected;
size_t _cacheSize;
friend class TileStore;
};
inline TileIndex::TileIndex() : id(Invalid) {}
inline TileIndex::TileIndex(uint8_t level, uint32_t row, uint32_t column) {
id = ((Storage(level) & ((1 << LevelBits) - 1)) << (RowBits + ColumnBits)) |
((Storage(row) & ((1 << RowBits) - 1)) << ColumnBits) |
(Storage(column) & ((1 << ColumnBits) - 1));
}
inline uint8_t TileIndex::level() const {
return (id >> (RowBits + ColumnBits)) & ((1 << LevelBits) - 1);
}
inline uint32_t TileIndex::row() const {
return (id >> ColumnBits) & ((1 << RowBits) - 1);
}
inline uint32_t TileIndex::column() const {
return id & ((1 << ColumnBits) - 1);
}
inline TileIndex TileIndex::parent() const {
auto l = level();
return l ? TileIndex(l-1, row() >> 1, column() >> 1) : TileIndex();
}
inline bool TileIndex::operator==(const TileIndex &other) const {
return id == other.id;
}
inline bool TileIndex::operator!=(const TileIndex &other) const {
return id != other.id;
}
inline bool TileIndex::operator<(const TileIndex &other) const {
return id < other.id;
}
inline TileIndex::operator bool() const {
return id != Invalid;
}
inline std::ostream &operator<<(std::ostream &os, const TileIndex &index) {
os << static_cast<int>(index.level()) << "/" << index.row() << "/" << index.column();
return os;
}
}
}
}
#endif

View File

@ -0,0 +1,216 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYER_H
#define SEISCOMP_GUI_MAP_LAYER_H
#ifndef Q_MOC_RUN
#include <seiscomp/core/baseobject.h>
#include <seiscomp/core/interfacefactory.h>
#endif
#include <seiscomp/gui/qt.h>
#include <seiscomp/gui/map/legend.h>
#include <seiscomp/gui/map/mapsymbol.h>
#include <QObject>
class QContextMenuEvent;
class QKeyEvent;
class QMouseEvent;
class QDialog;
class QMenu;
class QPainter;
class QWidget;
namespace Seiscomp {
namespace Config {
class Config;
}
namespace Gui {
namespace Map {
class Canvas;
DEFINE_SMARTPOINTER(Layer);
class SC_GUI_API Layer : public QObject, public Seiscomp::Core::BaseObject {
Q_OBJECT
public:
enum UpdateHint {
Redraw = 0x00, // Just redraw
Position = 0x01, // Update the layers position
RasterLayer = 0x02 // Update the map base layer
};
Q_DECLARE_FLAGS(UpdateHints, UpdateHint)
typedef QList<Legend*> Legends;
public:
Layer(QObject* parent = nullptr);
virtual ~Layer();
public:
Layer &operator=(const Layer &other);
public:
void setToolTip(const QString &toolTip);
const QString &toolTip() const { return _toolTip; }
bool hasCursorShape() const { return _hasCustomShape; }
const Qt::CursorShape &cursorShape() const { return _cursorShape; }
void setCursorShape(const Qt::CursorShape &);
void unsetCursorShape();
void update(const UpdateHints & = UpdateHints());
virtual void setConfig(const std::string &/*config*/) {}
virtual void init(const Config::Config&);
virtual void draw(const Canvas*, QPainter&) {}
virtual Layer *clone() const { return nullptr; }
signals:
/// This signal is emitted when a legend was added to layer
void legendAdded(Legend *legend);
/// This signal is emitted when a legend was removed from layer
void legendRemoved(Legend *legend);
public slots:
void setAntiAliasingEnabled(bool);
virtual void setVisible(bool);
/** @brief Shows this layer. This methods was added with API 11. */
virtual void show();
/** @brief Hides this layer. This methods was added with API 11. */
virtual void hide();
public:
void setName(const QString&);
const QString &name() const;
void setDescription(const QString&);
const QString &description() const;
/**
* @brief Adds the legend to the layer. The ownership of the object
* goes to the layer.
* @param legend The legend
* @return True, if the legend was added
*/
bool addLegend(Legend *legend);
/**
* @brief Removes the legend from the layer and deletes the object.
* @param legend The legend
* @return True, if the legend was removed
*/
bool removeLegend(Legend *legend);
int legendCount() const { return _legends.count(); }
Legend *legend(int i) const;
const QList<Legend*> &legends() const { return _legends; }
bool isVisible() const;
bool isAntiAliasingEnabled() const;
void setDirty();
bool isDirty() const;
Canvas *canvas() const { return _canvas; }
public:
/**
* @brief Convenience function that returns the size in pixels of the
* layer. By default it forwards the request to the canvas if
* the layer is attached to canvas or an invalid size otherwise.
* @return The size of the layer.
*/
virtual QSize size() const;
virtual void calculateMapPosition(const Canvas *canvas);
virtual bool isInside(const QMouseEvent *event, const QPointF &geoPos);
virtual void baseBufferUpdated(Canvas *canvas, QPainter &painter);
virtual void bufferUpdated(Canvas *canvas, QPainter &painter);
virtual void handleEnterEvent();
virtual void handleLeaveEvent();
virtual bool filterContextMenuEvent(QContextMenuEvent*, QWidget*);
virtual bool filterKeyPressEvent(QKeyEvent *event);
virtual bool filterKeyReleaseEvent(QKeyEvent *event);
virtual bool filterMouseMoveEvent(QMouseEvent *event, const QPointF &geoPos);
virtual bool filterMousePressEvent(QMouseEvent *event, const QPointF &geoPos);
virtual bool filterMouseReleaseEvent(QMouseEvent *event, const QPointF &geoPos);
virtual bool filterMouseDoubleClickEvent(QMouseEvent *event, const QPointF &geoPos);
virtual QMenu *menu(QMenu*) const;
signals:
void updateRequested(const Layer::UpdateHints& = UpdateHints());
private:
QString _toolTip;
Qt::CursorShape _cursorShape;
bool _hasCustomShape;
Canvas *_canvas;
QString _name;
QString _description;
bool _visible;
bool _antiAliasing;
Legends _legends;
bool _dirty;
friend class Canvas;
};
inline bool Layer::isDirty() const {
return _dirty;
}
Q_DECLARE_OPERATORS_FOR_FLAGS(Layer::UpdateHints)
DEFINE_INTERFACE_FACTORY(Layer);
#define REGISTER_LAYER_INTERFACE(Class, Service) \
Seiscomp::Core::Generic::InterfaceFactory<Seiscomp::Gui::Map::Layer, Class> __##Class##InterfaceFactory__(Service)
} // namespace Map
} // namespce Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,65 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_ANNOTATION_LAYER_H__
#define SEISCOMP_GUI_MAP_LAYERS_ANNOTATION_LAYER_H__
#include <seiscomp/gui/map/annotations.h>
#include <seiscomp/gui/map/layer.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class AnnotationLayer : public Layer {
public:
AnnotationLayer(QObject* parent = nullptr,
Annotations *annotations = nullptr);
void setAnnotations(Annotations *annotations) {
_annotations = annotations;
}
Annotations *annotations() const {
return _annotations;
}
void draw(const Seiscomp::Gui::Map::Canvas*, QPainter &painter);
private:
typedef QList<QRect> Row;
typedef QVector<Row> Grid;
Annotations *_annotations;
};
} // ns Map
} // ns Gui
} // ns Seiscomp
#endif

View File

@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_CITIESLAYER_H
#define SEISCOMP_GUI_MAP_LAYERS_CITIESLAYER_H
#include <seiscomp/gui/qt.h>
#include <seiscomp/gui/map/layer.h>
#include <seiscomp/math/coord.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class Projection;
class SC_GUI_API CitiesLayer : public Layer {
public:
CitiesLayer(QObject* = nullptr);
virtual ~CitiesLayer();
virtual void init(const Config::Config&);
virtual void draw(const Canvas*, QPainter&);
void setSelectedCity(const Math::Geo::CityD*);
const Math::Geo::CityD* selectedCity() const;
private:
typedef QList<QRect> Row;
typedef QVector<Row> Grid;
private:
bool drawCity(QPainter&, Grid&, QFont&, bool&, bool&,
const Projection*, const Math::Geo::CityD&,
const QFontMetrics&, int, int);
private:
const Math::Geo::CityD *_selectedCity;
int _topPopulatedPlaces;
};
} // namespace Map
} // namespce Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,202 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_GEOFEATURELAYER_H
#define SEISCOMP_GUI_MAP_LAYERS_GEOFEATURELAYER_H
#include <seiscomp/gui/map/layer.h>
#ifndef Q_MOC_RUN
#include <seiscomp/geo/featureset.h>
#include <seiscomp/geo/index/quadtree.h>
#endif
#include <QImage>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class SC_GUI_API GeoFeatureLayer : public Layer,
virtual public Geo::GeoFeatureSetObserver {
Q_OBJECT
public:
GeoFeatureLayer(QObject *parent = nullptr);
virtual ~GeoFeatureLayer();
public:
/**
* @brief Returns a feature under the given coordinate.
* @param coord The coordinate.
* @return A pointer to the feature instance or nullptr. Do not delete
* the feature, its ownership is still at the global
* GeoFeatureSet.
*/
const Geo::GeoFeature *findFeature(const Geo::GeoCoordinate &coord) const;
/**
* @brief Convenience function for @findFeature(const Geo::GeoCoordinate &coord).
* @param lat The latitude of the coordinate
* @param lon The longitude of the coordinate
* @return See @findFeature(const Geo::GeoCoordinate &coord).
*/
const Geo::GeoFeature *findFeature(qreal lat, qreal lon) const;
/**
* @brief Renders the geofeatures on a given canvas with a given
* painter. This function is called from bufferUpdated.
* @param canvas The target canvas
* @param painter The painter to paint with
*/
void renderFeatures(Canvas *canvas, QPainter &painter);
virtual void setVisible(bool flag);
virtual void bufferUpdated(Canvas *canvas, QPainter &painter);
virtual QMenu *menu(QMenu*) const;
virtual void geoFeatureSetUpdated();
private slots:
void toggleFeatureVisibility(bool);
void disableFeatureVisibility();
void showFeatures();
void hideFeatures();
void reloadFeatures();
private:
void initLayerProperites();
private:
struct SC_GUI_API LayerProperties {
enum SymbolShape {
Disabled,
None,
Circle,
Triangle,
Square,
Diamond
};
const LayerProperties *parent{nullptr};
std::string name;
std::string title;
Qt::Orientation orientation{Qt::Vertical};
Qt::Alignment legendArea{Qt::AlignTop | Qt::AlignLeft};
QPainter::CompositionMode compositionMode{QPainter::CompositionMode_SourceOver};
std::string label;
int index{0};
bool visible{true};
QPen pen;
QBrush brush;
QFont font;
bool drawName{false};
bool debug{false};
int rank{-1};
int roughness{-1};
bool filled{false};
int symbolSize{8};
QImage symbolIcon;
QPoint symbolIconHotspot;
SymbolShape symbolShape{Disabled};
QPolygon symbolPolygon;
Qt::Alignment symbolNameAlignment{Qt::AlignTop | Qt::AlignHCenter};
int symbolNameMargin{3};
// derived members
QRect symbolRect;
LayerProperties(const std::string &name) : name(name) {}
LayerProperties(const std::string &name,
const LayerProperties *parent) {
*this = *parent;
this->name = name;
this->parent = parent;
this->title = std::string(); // Reset the legend title
}
bool isChild(const LayerProperties* child) const;
void read(const std::string &dataDir = "");
static SymbolShape getSymbolShape(const std::string &type);
};
struct CategoryNode {
CategoryNode(const Geo::Category*);
~CategoryNode();
CategoryNode *nodeForCategory(const Geo::Category *cat);
CategoryNode *nodeForProperties(const LayerProperties *props);
const Geo::Category *category;
LayerProperties *properties{nullptr};
std::vector<CategoryNode*> childs;
std::vector<CategoryNode*> childsByName;
Geo::QuadTree quadtree;
Geo::GeoBoundingBox bbox;
};
static bool compareByIndex(const LayerProperties *p1,
const LayerProperties *p2);
static bool compareNodeByIndex(const GeoFeatureLayer::CategoryNode *n1,
const GeoFeatureLayer::CategoryNode *n2);
static bool compareNodeByName(const GeoFeatureLayer::CategoryNode *n1,
const GeoFeatureLayer::CategoryNode *n2);
CategoryNode *createOrGetNodeForCategory(const Geo::Category *cat);
void buildLegends(CategoryNode *node);
QMenu *buildMenu(CategoryNode *node, QMenu *parentMenu) const;
void collectLegendItems(CategoryNode *node, QVector<LayerProperties*> &items);
void orderTree(CategoryNode *node);
void updateBbox(CategoryNode *node);
const Geo::GeoFeature *findFeature(CategoryNode *node,
const Geo::GeoCoordinate &coord) const;
bool toggleVisibility(CategoryNode *node, bool visible);
void drawFeatures(CategoryNode *node, Canvas *canvas,
QPainter &painter, const QPen &debugPen);
bool drawFeature(Canvas *canvas, QPainter *painter,
const QPen *debugPen, const LayerProperties *props,
const Geo::GeoFeature *f);
bool _initialized;
CategoryNode *_root;
};
}
}
}
#endif

View File

@ -0,0 +1,56 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_GRIDLAYER_H
#define SEISCOMP_GUI_MAP_LAYERS_GRIDLAYER_H
#include <seiscomp/gui/qt.h>
#include <seiscomp/gui/map/layer.h>
#include <seiscomp/math/coord.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class SC_GUI_API GridLayer : public Layer {
public:
GridLayer(QObject* = nullptr);
virtual ~GridLayer();
virtual void draw(const Canvas*, QPainter&);
void setGridDistance(const QPointF&);
const QPointF& gridDistance() const;
private:
QPointF _gridDistance;
};
} // namespace Map
} // namespce Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,108 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_SYMBOLLAYER_H
#define SEISCOMP_GUI_MAP_LAYERS_SYMBOLLAYER_H
#include <seiscomp/gui/map/layer.h>
#include <seiscomp/gui/map/mapsymbol.h>
#include <QList>
namespace Seiscomp {
namespace Gui {
namespace Map {
class SC_GUI_API SymbolLayer : public Layer {
// ----------------------------------------------------------------------
// Types
// ----------------------------------------------------------------------
public:
typedef QList<Symbol*> Symbols;
typedef Symbols::iterator iterator;
typedef Symbols::const_iterator const_iterator;
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
SymbolLayer(QObject* parent = nullptr);
//! D'tor
~SymbolLayer();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
/**
* @brief Adds a symbol to the layer.
* @param symbol The symbol instance. Ownership is transferred to
* the layer
* @return Success flag
*/
bool add(Symbol *symbol);
Symbols::const_iterator remove(Symbol *symbol);
void clear();
Symbols::size_type count() const;
bool bringToTop(Symbol *drawable);
bool sendToBack(Symbol *drawable);
void setTop(Symbol *topDrawable);
Symbol *top() const;
Symbols::iterator begin();
Symbols::iterator end();
Symbols::const_iterator begin() const;
Symbols::const_iterator end() const;
void sortByLatitude();
// ----------------------------------------------------------------------
// Layer interface
// ----------------------------------------------------------------------
public:
virtual void setVisible(bool);
virtual void calculateMapPosition(const Canvas *canvas);
virtual bool isInside(const QMouseEvent *event, const QPointF &geoPos);
virtual void draw(const Canvas *canvas, QPainter &p);
private:
Symbols _symbols;
Symbol *_topSymbol;
};
} // namespace Map
} // namespace Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,133 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LEGEND_H
#define SEISCOMP_GUI_MAP_LEGEND_H
#ifndef Q_MOC_RUN
#include <seiscomp/core/baseobject.h>
#endif
#include <seiscomp/gui/qt.h>
#include <QFont>
#include <QSize>
#include <QString>
#include <QObject>
#include <QPoint>
class QPainter;
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class Layer;
class SC_GUI_API Legend : public QObject {
Q_OBJECT
public:
Legend(QObject *parent = nullptr);
Legend(const QString&, QObject *parent = nullptr);
virtual ~Legend() {}
Legend &operator =(const Legend &other);
virtual void bringToFront();
virtual Legend* clone() const { return nullptr; }
virtual void draw(const QRect&, QPainter&) = 0;
Qt::Alignment alignment() const { return _alignment; }
void setArea(Qt::Alignment alignment) { _alignment = alignment; }
void setEnabled(bool);
bool isEnabled() const;
const QFont& font() const { return _font; }
void setFont(const QFont &font) { _font = font; }
Layer *layer() const { return _layer; }
void setLayer(Layer* layer) { _layer = layer; }
int margin() const { return _margin; }
void setMargin(int margin) { _margin = margin; }
int spacing() const { return _spacing; }
void setSpacing(int spacing) { _spacing = spacing; }
const QString& title() const { return _title; }
void setTitle(const QString &title) { _title = title; }
const QFont& titleFont() const { return _titleFont; }
void setTitleFont(const QFont &font) { _titleFont = font; }
bool isVisible() const { return _visible; }
const QSize &size() const { return _size; }
virtual void contextResizeEvent(const QSize &size) {}
signals:
void bringToFrontRequested(Seiscomp::Gui::Map::Legend*);
void enabled(Seiscomp::Gui::Map::Legend*, bool);
void visibilityChanged(bool);
private:
void setVisible(bool visible) {
_visible = visible;
emit visibilityChanged(visible);
}
protected:
int _margin;
int _spacing;
QFont _font;
QFont _titleFont;
QSize _size;
Layer *_layer;
QString _title;
Qt::Alignment _alignment;
bool _enabled;
QPoint _pos;
bool _visible;
friend class Canvas;
};
} // namespace Map
} // namespce Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,293 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAPSYMBOL_H
#define SEISCOMP_GUI_MAPSYMBOL_H
#include <QPolygon>
#include <QColor>
#ifndef Q_MOC_RUN
#include <seiscomp/core/baseobject.h>
#endif
#include <seiscomp/gui/map/decorator.h>
#include <seiscomp/gui/qt.h>
class QPainter;
namespace Seiscomp {
namespace Gui {
namespace Map {
class Canvas;
class SC_GUI_API Symbol {
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
public:
enum Priority {
NONE = 0x0,
LOW,
MEDIUM,
HIGH
};
// ----------------------------------------------------------------------
// X'struction
// ----------------------------------------------------------------------
protected:
//! C'tor
Symbol(Decorator* decorator = nullptr);
Symbol(double lat, double lon, Decorator* decorator = nullptr);
Symbol(const QPointF &latlon, Decorator* decorator = nullptr);
public:
virtual ~Symbol();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
/**
* @brief Draws the symbol. If a decorator is attached to the symbol
* it is drawn first. To implement the actual painting of a
* symbol, implement @customDraw.
* @param canvas The canvas the symbol is rendered on.
* @param painter The painter object.
*/
void draw(const Map::Canvas *canvas, QPainter &painter);
/**
* @brief Sets an arbitrary type. The canvas does not use this attribute
* for rendering. The type can be used in application code for
* any purpose.
* @param type The new type id
*/
void setType(int type);
int type() const;
/**
* @brief Sets an arbitrary ID. The canvas does not use this attribute
* for rendering. The ID can be used in application code for
* any purpose.
* @param id The new ID
*/
void setID(const std::string &id);
/**
* @brief Returns the (arbitrary) id of the symbol.
* @return A string reference to the id
*/
const std::string &id() const;
//! Returns the current render priority.
Priority priority() const;
/**
* @brief Sets the symbols priority on the map. The higher the priority
* the higher the layer it is rendered onto.
* @param priority The priority to be set.
*/
void setPriority(Priority priority);
//! Returns the state of the clipping flag
bool isClipped() const;
//! Toggles the visibility flag
void setVisible(bool visible);
//! Returns the state of the visibility flag
bool isVisible() const;
//! Sets the current size
void setSize(const QSize &size);
//! Returns the current size
const QSize &size() const;
void setLocation(double latitude, double longitude);
void setLocation(const QPointF &latlon);
void setLatitude(double lat);
void setLongitude(double lon);
//! Returns the current map location
const QPointF location() const;
double longitude() const;
double latitude() const;
//! Return the current map position
const QPoint &pos() const;
//! Returns whether the map position is valid or not
bool hasValidPosition() const;
//! Returns the screen x position
int x() const;
//! Returns the screen y position
int y() const;
void setDecorator(Decorator *);
//! Returns the attached decorator
Decorator *decorator() const;
// ----------------------------------------------------------------------
// Public symbol interface
// ----------------------------------------------------------------------
public:
/**
* @brief Check whether a point in canvas coordinates is inside
* the symbol. Because a symbol has no associated shape, it
* can't provide a default implementation.
* @param x The x coordinate
* @param y The y coordinate
* @return true is (x,y) is inside the symbol, false otherwise
*/
virtual bool isInside(int x, int y) const = 0;
/**
* @brief Calculates the map position of the symbols geo location.
* The default implementation projects the geo location to the
* map position and sets the clipping according to the result.
* The default implementation should be sufficient for almost any use
* case. If required, then derived classes can add their own
* implementation for this method.
* @param canvas
*/
virtual void calculateMapPosition(const Map::Canvas *canvas);
/**
* @brief Draws a symbol. This method must be implemented by derived
* classes.
* @param canvas The canvas to paint onto.
* @param painter The painter to paint with.
*/
virtual void customDraw(const Map::Canvas *canvas, QPainter &painter) = 0;
/**
* @brief Notifies the symbol that the layer visibility has changed.
* @param v The current visibility
*/
virtual void layerVisibilityChanged(bool v);
// ----------------------------------------------------------------------
// Protected symbol interface
// ----------------------------------------------------------------------
protected:
/**
* @brief Sets the clipping flag
* @param clipped The flag
*/
void setClipped(bool clipped);
// ----------------------------------------------------------------------
// Private data members
// ----------------------------------------------------------------------
protected:
int _type;
std::string _id;
Priority _priority;
bool _clipped;
bool _visible;
QPointF _location;
QPoint _position;
QSize _size;
std::unique_ptr<Decorator> _decorator;
};
inline int Symbol::type() const {
return _type;
}
inline const std::string &Symbol::id() const {
return _id;
}
inline Symbol::Priority Symbol::priority() const {
return _priority;
}
inline bool Symbol::isClipped() const {
return _clipped;
}
inline bool Symbol::isVisible() const {
return _visible;
}
inline const QSize &Symbol::size() const {
return _size;
}
inline const QPointF Symbol::location() const {
return _location;
}
inline double Symbol::latitude() const {
return _location.y();
}
inline double Symbol::longitude() const {
return _location.x();
}
inline const QPoint &Symbol::pos() const {
return _position;
}
inline int Symbol::x() const {
return _position.x();
}
inline int Symbol::y() const {
return _position.y();
}
inline bool Symbol::hasValidPosition() const {
return _position.x() >= 0 || _position.y() >= 0;
}
inline Decorator *Symbol::decorator() const {
return _decorator.get();
}
} // namespace Map
} // namespace Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,169 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAPWIDGET_H
#define SEISCOMP_GUI_MAPWIDGET_H
#include <seiscomp/gui/map/canvas.h>
#ifndef Q_MOC_RUN
#include <seiscomp/math/coord.h>
#endif
#include <QColor>
#include <QDialog>
#include <QPen>
#include <QtGui>
class QLineEdit;
class QCheckBox;
class QSpinBox;
namespace Seiscomp {
namespace Gui {
class SaveBNADialog : public QDialog {
Q_OBJECT
public:
SaveBNADialog(QWidget *parent = 0, Qt::WindowFlags f = Qt::WindowFlags());
public:
QLineEdit *name;
QCheckBox *closedPolygon;
QCheckBox *fileAppend;
QSpinBox *rank;
QLineEdit *filename;
};
class SC_GUI_API MapWidget : public QWidget {
Q_OBJECT
public:
MapWidget(QWidget *parent = 0, Qt::WindowFlags f = Qt::WindowFlags());
MapWidget(const MapsDesc &meta, QWidget *parent = 0, Qt::WindowFlags f = Qt::WindowFlags());
MapWidget(Map::ImageTree *mapTree, QWidget *parent = 0, Qt::WindowFlags f = Qt::WindowFlags());
virtual ~MapWidget();
Map::Canvas &canvas() { return _canvas; }
const Map::Canvas &canvas() const { return _canvas; }
int heightForWidth(int w) const;
bool isGrayScale() const;
bool isMeasuring() const;
bool isDragging() const;
bool saveScreenshot();
virtual void draw(QPainter&);
public slots:
/**
* @brief Sets map rendering in grayscale mode even if the widget is
* enabled.
* @param f The enable flag
*/
void setGrayScale(bool f);
void setDrawGrid(bool);
void setDrawLayers(bool);
void setDrawCities(bool);
void setDrawLegends(bool);
protected slots:
virtual void bufferUpdated();
virtual void drawCustomLayer(QPainter *p) {}
private slots:
void projectionChanged(Seiscomp::Gui::Map::Projection*);
void zoomIn();
void zoomOut();
signals:
void keyPressed(QKeyEvent*);
protected:
void paintEvent(QPaintEvent*);
void resizeEvent(QResizeEvent*);
void mousePressEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
void mouseDoubleClickEvent(QMouseEvent*);
void keyPressEvent(QKeyEvent*);
void keyReleaseEvent(QKeyEvent*);
void wheelEvent(QWheelEvent*);
void contextMenuEvent(QContextMenuEvent*);
void leaveEvent(QEvent*);
void updateContextMenu(QMenu *menu);
void executeContextMenuAction(QAction *action);
private:
void init();
private:
Map::Canvas _canvas;
std::string _currentProjection;
bool _firstDrag;
bool _isDragging;
bool _isMeasuring;
bool _filterMap;
bool _forceGrayScale;
QVector<QPointF> _measurePoints;
QString _measureText;
SaveBNADialog *_measureBNADialog;
QPoint _lastDraggingPosition;
QMenu *_contextProjectionMenu;
QMenu *_contextFilterMenu;
double _zoomSensitivity;
QWidget *_zoomControls;
};
inline bool MapWidget::isMeasuring() const {
return _isMeasuring;
}
inline bool MapWidget::isDragging() const {
return _isDragging;
}
}
}
#endif

View File

@ -0,0 +1,86 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_PROJECTIONS_MERCATOR_H
#define SEISCOMP_GUI_MAP_PROJECTIONS_MERCATOR_H
#include <QImage>
#include <seiscomp/gui/map/mapwidget.h>
#include <seiscomp/gui/map/projections/rectangular.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class SC_GUI_API MercatorProjection : public RectangularProjection {
// ----------------------------------------------------------------------
// X'struction
// ----------------------------------------------------------------------
public:
MercatorProjection();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
virtual bool isRectangular() const;
virtual bool project(QPoint &screenCoords, const QPointF &geoCoords) const;
virtual bool unproject(QPointF &geoCoords, const QPoint &screenCoords) const;
virtual void centerOn(const QPointF &geoCoords);
virtual QPointF gridDistance() const;
virtual void drawImage(QImage &buffer, const QRectF &geoReference,
const QImage &image,
bool highQuality, CompositionMode compositionMode);
virtual bool project(QPainterPath &screenPath, size_t n,
const Geo::GeoCoordinate *poly, bool closed,
uint minPixelDist, ClipHint hint = NoClip) const;
protected:
template <typename PROC>
void render(QImage &img, TextureCache *cache);
void render(QImage &img, bool highQuality, TextureCache *cache);
void projectUnwrapped(QPoint &screenCoords, const QPointF &geoCoords) const;
protected:
QRect _windowRect;
QRect _clipRect;
qreal _centerY;
bool _discreteSteps;
};
}
}
}
#endif

View File

@ -0,0 +1,309 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_PROJECTION_H
#define SEISCOMP_GUI_MAP_PROJECTION_H
#include <seiscomp/core/interfacefactory.h>
#include <seiscomp/geo/boundingbox.h>
#include <seiscomp/gui/map/texturecache.h>
#include <seiscomp/gui/qt.h>
#include <QPainterPath>
#include <QImage>
namespace Seiscomp {
namespace Gui {
namespace Map {
/**
* @brief The CompositionMode enum define composition modes when
* drawing an image.
*/
enum CompositionMode {
CompositionMode_Default, // Either Source or SourceOver depending on image format.
CompositionMode_Source, // Image pixels replace map pixels.
CompositionMode_SourceOver, // Image pixels are blended with map according
// to the image pixels alpha value.
CompositionMode_Xor, // Colors are bitwise xor'd
CompositionMode_Plus, // Colors are added together
CompositionMode_Multiply // Image pixels are multiplied with map pixels, alpha
// is ignored.
};
/**
* @brief The FilterMode enum define filter modes when drawing images and
* map tiles.
*/
enum FilterMode {
FilterMode_Auto, // Let the canvas decide how to filter the image
FilterMode_Nearest, // The nearest image pixel for a subpixel is used
FilterMode_Bilinear // The four neighbor pixels are interpolated for a subpixel
};
enum ClipHint {
NoClip, // Clipping not necessary, bounding box is completely contained
DoClip // Clipping would help to reduce render time
};
// All QPointF instances are geographical coordinates where
// x = longitude and y = latitude.
class SC_GUI_API Projection {
// ----------------------------------------------------------------------
// X'struction
// ----------------------------------------------------------------------
public:
Projection();
virtual ~Projection();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
void setBackgroundColor(const QColor &c);
void setZoom(qreal zoom);
qreal zoom() const;
qreal visibleZoom() const;
qreal pixelPerDegree() const;
virtual QPointF gridDistance() const;
void setView(const QPointF &geoCoords, qreal zoom);
QPointF center() const;
QPointF visibleCenter() const;
void draw(QImage &buffer, bool filter, TextureCache *cache);
virtual bool isRectangular() const = 0;
virtual bool wantsGridAntialiasing() const = 0;
/**
* @brief Updates the visible map bounding box. This function will be
* called *after* rendering, so after calling
* @render(QImage &, bool, TextureCache *).
*/
virtual void updateBoundingBox();
/**
* @brief Returns the current visible map bounding box. Note that this
* bounding box will only be valid after the projection has
* been rendered otherwise it will be in an undefined state.
* @return The bounding box currently visible.
*/
const Geo::GeoBoundingBox &boundingBox() const;
virtual bool project(QPoint &screenCoords, const QPointF &geoCoords) const = 0;
virtual bool unproject(QPointF &geoCoords, const QPoint &screenCoords) const = 0;
virtual void centerOn(const QPointF &geoCoords) = 0;
virtual void displayRect(const QRectF& rect);
virtual void drawImage(QImage &buffer, const QRectF &geoReference, const QImage &image, bool highQuality,
CompositionMode compositionMode = CompositionMode_Default);
//! Returns the number of interpolation steps when drawing a
//! geometric line.
virtual int lineSteps(const QPointF &p0, const QPointF &p1);
//! Draws a straight line. Returns false, when the whole line has been clipped
//! completely otherwise true.
virtual bool drawLine(QPainter &p, const QPointF &from, const QPointF &to);
virtual void moveTo(const QPointF &p);
virtual bool lineTo(QPainter &p, const QPointF &to);
virtual bool drawLatCircle(QPainter &p, qreal lon);
virtual bool drawLonCircle(QPainter &p, qreal lat);
/**
* Returns true if the GUI object, represented by its bounding box in geo
* coordinates, does not intersect the canvas. Note: The default
* implementation checks clipping against the map bounding box which is
* perfectly OK in all situations given the bounding box is computed
* correctly. If more complex checks needs to be implemented, then
* override this method. The default implementation just calls
* @isClipped(const Geo::GeoBoundingBox &).
*
* Warning: This method is deprecated. In future this virtual method
* will be removed and the only clipping check will be against the map
* bounding box. There is no need to delegate clipping to custom
* projections as long as a correct bounding box is maintained.
*/
virtual bool isClipped(const QPointF &bboxLR, const QPointF &bboxUL) const;
bool isClipped(const Geo::GeoBoundingBox &bbox) const;
/**
* @brief Projects a closed input geo polygon to a QPainterPath
* @param screenPath The painter path in screen coordinates. That
* path must represent the input polygon on screen.
* @param n The number of input coordinates
* @param poly The coordinates of the polygon. The polygon is assumed
* to be closed.
* @param minPixelDist The minimum pixel distance two coordinates must
* have to become two separate projections on screen.
* If their distance is less then the coordinates
* will collapse into a single pixel.
* @return A flag that defines wether the returned path is valid.
*/
virtual bool project(QPainterPath &screenPath, size_t n,
const Geo::GeoCoordinate *poly, bool closed,
uint minPixelDist, ClipHint hint = NoClip) const;
/**
*@brief Sets the number of grid lines for the largest screen dimension.
* The specified number is used in the grid distance calculation,
* @see gridDistance()
*@since API Version 12.0.0
*/
void setGridLines(qreal numLines);
protected:
void setSize(int width, int height);
void setVisibleRadius(qreal r);
virtual void render(QImage &img, bool highQuality, TextureCache *cache) = 0;
// ----------------------------------------------------------------------
// Protected member
// ----------------------------------------------------------------------
protected:
qreal _radius;
qreal _visibleRadius;
qreal _pixelPerDegreeFact;
int _width;
int _height;
int _halfWidth;
int _halfHeight;
qreal _screenRadius;
qreal _mapWidth;
qreal _halfMapWidth;
qreal _scale;
qreal _oneOverScale;
QPointF _center;
QPointF _visibleCenter;
QPoint _cursor;
bool _cursorVisible;
QRgb _background;
qreal _gridLines;
Geo::GeoBoundingBox _mapBoundingBox;
};
DEFINE_INTERFACE_FACTORY(Projection);
inline const Geo::GeoBoundingBox &Projection::boundingBox() const {
return _mapBoundingBox;
}
#define REGISTER_PROJECTION_INTERFACE(Class, Service) \
Seiscomp::Core::Generic::InterfaceFactory<Seiscomp::Gui::Map::Projection, Class> __##Class##InterfaceFactory__(Service)
struct NearestFilter {
static void fetch(TextureCache *cache, QRgb &c, Coord u, Coord v, int level) {
cache->getTexel(c,u,v,level);
}
};
struct BilinearFilter {
static void fetch(TextureCache *cache, QRgb &c, Coord u, Coord v, int level) {
cache->getTexelBilinear(c,u,v,level);
}
};
struct CompositionSourceOver {
static void combine(QRgb &target, QRgb source) {
int alpha = qAlpha(source);
int iAlpha = 255 - alpha;
target = qRgb(
(qRed(source)*alpha + qRed(target)*iAlpha) >> 8,
(qGreen(source)*alpha + qGreen(target)*iAlpha) >> 8,
(qBlue(source)*alpha + qBlue(target)*iAlpha) >> 8
);
}
};
struct CompositionSource {
static void combine(QRgb &target, QRgb source) {
target = source;
}
};
struct CompositionMultiply {
static void combine(QRgb &target, QRgb source) {
target = qRgb(
(qRed(source) * qRed(target)) >> 8,
(qGreen(source) * qGreen(target)) >> 8,
(qBlue(source) * qBlue(target)) >> 8
);
}
};
struct CompositionXor {
static void combine(QRgb &target, QRgb source) {
target = qRgb(
(qRed(source) xor qRed(target)),
(qGreen(source) xor qGreen(target)),
(qBlue(source) xor qBlue(target))
);
}
};
struct CompositionPlus {
static void combine(QRgb &target, QRgb source) {
int r = qRed(source) + qRed(target);
int g = qGreen(source) + qGreen(target);
int b = qBlue(source) + qBlue(target);
target = qRgb(r > 255 ? 255 : r, g > 255 ? 255 : g, b > 255 ? 255 : b);
}
};
}
}
}
#endif

View File

@ -0,0 +1,86 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_PROJECTIONS_MERCATOR_H
#define SEISCOMP_GUI_MAP_PROJECTIONS_MERCATOR_H
#include <QImage>
#include <seiscomp/gui/map/mapwidget.h>
#include <seiscomp/gui/map/projections/rectangular.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class SC_GUI_API MercatorProjection : public RectangularProjection {
// ----------------------------------------------------------------------
// X'struction
// ----------------------------------------------------------------------
public:
MercatorProjection();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
virtual bool isRectangular() const;
virtual bool project(QPoint &screenCoords, const QPointF &geoCoords) const;
virtual bool unproject(QPointF &geoCoords, const QPoint &screenCoords) const;
virtual void centerOn(const QPointF &geoCoords);
virtual QPointF gridDistance() const;
virtual void drawImage(QImage &buffer, const QRectF &geoReference,
const QImage &image,
bool highQuality, CompositionMode compositionMode);
virtual bool project(QPainterPath &screenPath, size_t n,
const Geo::GeoCoordinate *poly, bool closed,
uint minPixelDist, ClipHint hint = NoClip) const;
protected:
template <typename PROC>
void render(QImage &img, TextureCache *cache);
void render(QImage &img, bool highQuality, TextureCache *cache);
void projectUnwrapped(QPoint &screenCoords, const QPointF &geoCoords) const;
protected:
QRect _windowRect;
QRect _clipRect;
qreal _centerY;
bool _discreteSteps;
};
}
}
}
#endif

View File

@ -0,0 +1,104 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_PROJECTIONS_RECTANGULAR_H
#define SEISCOMP_GUI_MAP_PROJECTIONS_RECTANGULAR_H
#include <QImage>
#include <seiscomp/gui/map/mapwidget.h>
#include <seiscomp/gui/map/projection.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class SC_GUI_API RectangularProjection : public Projection {
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
RectangularProjection();
// ----------------------------------------------------------------------
// Public projection interface
// ----------------------------------------------------------------------
public:
void setLowZoomEnabled(bool);
virtual bool isRectangular() const;
virtual bool wantsGridAntialiasing() const;
virtual bool project(QPoint &screenCoords, const QPointF &geoCoords) const;
virtual bool unproject(QPointF &geoCoords, const QPoint &screenCoords) const;
virtual void centerOn(const QPointF &geoCoords);
virtual int lineSteps(const QPointF &p0, const QPointF &p1);
virtual void drawImage(QImage &buffer, const QRectF &geoReference,
const QImage &image, bool highQuality,
CompositionMode cm);
virtual bool drawLine(QPainter &p, const QPointF &from, const QPointF &to);
virtual void moveTo(const QPointF &p);
virtual bool lineTo(QPainter &p, const QPointF &to);
virtual bool drawLatCircle(QPainter &p, qreal lon);
virtual bool drawLonCircle(QPainter &p, qreal lat);
virtual bool project(QPainterPath &screenPath, size_t n,
const Geo::GeoCoordinate *poly, bool closed,
uint minPixelDist, ClipHint hint = NoClip) const;
protected:
template <typename PROC>
void render(QImage &img, TextureCache *cache);
void render(QImage &img, bool highQuality, TextureCache *cache);
void projectUnwrapped(QPoint &screenCoords, const QPointF &geoCoords) const;
// ----------------------------------------------------------------------
// Protected member
// ----------------------------------------------------------------------
protected:
bool _enableLowZoom;
// ----------------------------------------------------------------------
// Private member
// ----------------------------------------------------------------------
private:
qreal _cursorLon;
};
}
}
}
#endif

View File

@ -0,0 +1,104 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_PROJECTIONS_RECTANGULAR_H
#define SEISCOMP_GUI_MAP_PROJECTIONS_RECTANGULAR_H
#include <QImage>
#include <seiscomp/gui/map/mapwidget.h>
#include <seiscomp/gui/map/projection.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class SC_GUI_API RectangularProjection : public Projection {
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
RectangularProjection();
// ----------------------------------------------------------------------
// Public projection interface
// ----------------------------------------------------------------------
public:
void setLowZoomEnabled(bool);
virtual bool isRectangular() const;
virtual bool wantsGridAntialiasing() const;
virtual bool project(QPoint &screenCoords, const QPointF &geoCoords) const;
virtual bool unproject(QPointF &geoCoords, const QPoint &screenCoords) const;
virtual void centerOn(const QPointF &geoCoords);
virtual int lineSteps(const QPointF &p0, const QPointF &p1);
virtual void drawImage(QImage &buffer, const QRectF &geoReference,
const QImage &image, bool highQuality,
CompositionMode cm);
virtual bool drawLine(QPainter &p, const QPointF &from, const QPointF &to);
virtual void moveTo(const QPointF &p);
virtual bool lineTo(QPainter &p, const QPointF &to);
virtual bool drawLatCircle(QPainter &p, qreal lon);
virtual bool drawLonCircle(QPainter &p, qreal lat);
virtual bool project(QPainterPath &screenPath, size_t n,
const Geo::GeoCoordinate *poly, bool closed,
uint minPixelDist, ClipHint hint = NoClip) const;
protected:
template <typename PROC>
void render(QImage &img, TextureCache *cache);
void render(QImage &img, bool highQuality, TextureCache *cache);
void projectUnwrapped(QPoint &screenCoords, const QPointF &geoCoords) const;
// ----------------------------------------------------------------------
// Protected member
// ----------------------------------------------------------------------
protected:
bool _enableLowZoom;
// ----------------------------------------------------------------------
// Private member
// ----------------------------------------------------------------------
private:
qreal _cursorLon;
};
}
}
}
#endif

View File

@ -0,0 +1,108 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_LAYERS_SYMBOLLAYER_H
#define SEISCOMP_GUI_MAP_LAYERS_SYMBOLLAYER_H
#include <seiscomp/gui/map/layer.h>
#include <seiscomp/gui/map/mapsymbol.h>
#include <QList>
namespace Seiscomp {
namespace Gui {
namespace Map {
class SC_GUI_API SymbolLayer : public Layer {
// ----------------------------------------------------------------------
// Types
// ----------------------------------------------------------------------
public:
typedef QList<Symbol*> Symbols;
typedef Symbols::iterator iterator;
typedef Symbols::const_iterator const_iterator;
// ----------------------------------------------------------------------
// X'truction
// ----------------------------------------------------------------------
public:
//! C'tor
SymbolLayer(QObject* parent = nullptr);
//! D'tor
~SymbolLayer();
// ----------------------------------------------------------------------
// Public interface
// ----------------------------------------------------------------------
public:
/**
* @brief Adds a symbol to the layer.
* @param symbol The symbol instance. Ownership is transferred to
* the layer
* @return Success flag
*/
bool add(Symbol *symbol);
Symbols::const_iterator remove(Symbol *symbol);
void clear();
Symbols::size_type count() const;
bool bringToTop(Symbol *drawable);
bool sendToBack(Symbol *drawable);
void setTop(Symbol *topDrawable);
Symbol *top() const;
Symbols::iterator begin();
Symbols::iterator end();
Symbols::const_iterator begin() const;
Symbols::const_iterator end() const;
void sortByLatitude();
// ----------------------------------------------------------------------
// Layer interface
// ----------------------------------------------------------------------
public:
virtual void setVisible(bool);
virtual void calculateMapPosition(const Canvas *canvas);
virtual bool isInside(const QMouseEvent *event, const QPointF &geoPos);
virtual void draw(const Canvas *canvas, QPainter &p);
private:
Symbols _symbols;
Symbol *_topSymbol;
};
} // namespace Map
} // namespace Gui
} // namespace Seiscomp
#endif

View File

@ -0,0 +1,166 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
#ifndef SEISCOMP_GUI_MAP_TEXTURECACHE_H
#define SEISCOMP_GUI_MAP_TEXTURECACHE_H
#include <QHash>
#include <QMap>
#include <QImage>
#include <QPair>
#ifndef Q_MOC_RUN
#include <seiscomp/core/baseobject.h>
#include <seiscomp/core/datetime.h>
#endif
#include <seiscomp/gui/map/imagetree.h>
namespace Seiscomp {
namespace Gui {
namespace Map {
class TextureCache;
class TileStore;
union Coord {
enum limits {
fraction_half_max = Q_INT64_C(2147483648),
fraction_max = Q_INT64_C(4294967296),
fraction_shift = 32
};
typedef qint64 value_type;
typedef quint32 part_type;
Coord() {}
Coord(value_type v) : value(v) {}
struct {
part_type lo;
part_type hi;
} parts;
value_type value;
};
DEFINE_SMARTPOINTER(Texture);
struct SC_GUI_API Texture : public Core::BaseObject {
Texture(bool isDummy = false);
int numBytes() const;
void setImage(QImage &img);
QImage image;
const QRgb *data;
TileIndex id;
quint32 w;
quint32 h;
quint64 lastUsed;
bool isDummy;
};
DEFINE_SMARTPOINTER(TextureCache);
class SC_GUI_API TextureCache : public Core::BaseObject {
public:
TextureCache(TileStore *mapTree, bool mercatorProjected);
~TextureCache();
void beginPaint();
void setCacheLimit(int limit);
void setCurrentTime(const Core::Time &t);
int maxLevel() const;
int tileWidth() const;
int tileHeight() const;
bool isMercatorProjected() const { return _isMercatorProjected; }
void getTexel(QRgb &c, Coord u, Coord v, int level);
void getTexelBilinear(QRgb &c, Coord u, Coord v, int level);
Texture *get(const TileIndex &id);
const quint64 &startTick() const { return _currentTick; }
bool load(QImage &img, const TileIndex &tile);
TileStore::LoadResult load2(QImage &img, const TileIndex &tile);
bool setTexture(QImage &img, const TileIndex &tile);
bool setTextureOrLoadParent(QImage &img, const TileIndex &tile);
//! Invalidates a texture and causes load() to be called next time
//! it needs to be accessed.
//! This function was introduced in API 1.1
void invalidateTexture(const TileIndex &tile);
//! Clears the cache
void clear();
private:
void cache(Texture *tex);
void checkResources(Texture *tex = nullptr);
Texture *fetch(const TileIndex &tile, bool &deferred);
static void remove(const QString &name);
private:
typedef std::map<TileIndex, TexturePtr> Storage;
typedef std::map<TileIndex, Texture*> InvalidMapping;
TileStore *_tileStore;
bool _isMercatorProjected;
Storage _storage;
int _storedBytes;
int _textureCacheLimit;
quint64 _currentTick;
InvalidMapping _invalidMapping;
Texture *_lastTile[2];
TileIndex _lastId[2];
int _currentIndex;
typedef QPair<QImage, int> CacheEntry;
typedef QMap<QString, CacheEntry> ImageCache;
static ImageCache _images;
};
void getTexel(QRgb &c, const QRgb *data, int w, int h, Coord u, Coord v);
void getTexelBilinear(QRgb &c, const QRgb *data, int w, int h, Coord u, Coord v);
}
}
}
#endif

View File

@ -0,0 +1,223 @@
/***************************************************************************
* Copyright (C) gempa GmbH *
* All rights reserved. *
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
* *
* GNU Affero General Public License Usage *
* This file may be used under the terms of the GNU Affero *
* Public License version 3.0 as published by the Free Software Foundation *
* and appearing in the file LICENSE included in the packaging of this *
* file. Please review the following information to ensure the GNU Affero *
* Public License version 3.0 requirements will be met: *
* https://www.gnu.org/licenses/agpl-3.0.html. *
* *
* Other Usage *
* Alternatively, this file may be used in accordance with the terms and *
* conditions contained in a signed written agreement between you and *
* gempa GmbH. *
***************************************************************************/
namespace Seiscomp {
namespace Gui {
namespace Map {
inline void TextureCache::getTexel(QRgb &c, Coord u, Coord v, int level) {
u.parts.hi = 0;
v.parts.hi = 0;
TileIndex id(level, (v.value << level) >> Coord::fraction_shift, (u.value << level) >> Coord::fraction_shift);
Texture *tex;
if ( !_lastTile[0] || _lastId[0] != id ) {
if ( !_lastTile[1] || _lastId[1] != id ) {
tex = get(id);
_lastTile[_currentIndex] = tex;
_lastId[_currentIndex] = id;
_currentIndex = 1-_currentIndex;
}
else {
tex = _lastTile[1];
}
}
else
tex = _lastTile[0];
u.value <<= tex->id.level();
v.value <<= tex->id.level();
u.value = Coord::value_type(u.parts.lo) * tex->w;
v.value = Coord::value_type(v.parts.lo) * tex->h;
c = tex->data[v.parts.hi*tex->w +u.parts.hi];
}
inline void TextureCache::getTexelBilinear(QRgb &c, Coord u, Coord v, int level) {
u.parts.hi = 0;
v.parts.hi = 0;
TileIndex id(level, (v.value << level) >> Coord::fraction_shift, (u.value << level) >> Coord::fraction_shift);
Texture *tex;
if ( !_lastTile[0] || _lastId[0] != id ) {
if ( !_lastTile[1] || _lastId[1] != id ) {
tex = get(id);
_lastTile[_currentIndex] = tex;
_lastId[_currentIndex] = id;
_currentIndex = 1-_currentIndex;
}
else {
tex = _lastTile[1];
}
}
else
tex = _lastTile[0];
u.value <<= tex->id.level();
v.value <<= tex->id.level();
u.value = Coord::value_type(u.parts.lo) * tex->w;
v.value = Coord::value_type(v.parts.lo) * tex->h;
Coord::part_type itnx = u.parts.hi + 1;
Coord::part_type itny = v.parts.hi + 1;
if ( itnx < tex->w ) {
if ( itny < tex->h ) {
int tidx = v.parts.hi*tex->w + u.parts.hi;
QRgb t = tex->data[tidx];
QRgb tnx = tex->data[tidx + 1];
QRgb tny = tex->data[tidx + tex->w];
QRgb tnxy = tex->data[tidx + tex->w + 1];
Coord::value_type ftx = u.parts.lo;
Coord::value_type fty = v.parts.lo;
Coord::value_type iftx = Coord::fraction_max - ftx;
Coord::value_type ifty = Coord::fraction_max - fty;
QRgb y0 = qRgb((qRed(t) * iftx + qRed(tnx) * ftx) >> Coord::fraction_shift,
(qGreen(t) * iftx + qGreen(tnx) * ftx) >> Coord::fraction_shift,
(qBlue(t) * iftx + qBlue(tnx) * ftx) >> Coord::fraction_shift);
QRgb y1 = qRgb((qRed(tny) * iftx + qRed(tnxy) * ftx) >> Coord::fraction_shift,
(qGreen(tny) * iftx + qGreen(tnxy) * ftx) >> Coord::fraction_shift,
(qBlue(tny) * iftx + qBlue(tnxy) * ftx) >> Coord::fraction_shift);
c = qRgb((qRed(y0) * ifty + qRed(y1) * fty) >> Coord::fraction_shift,
(qGreen(y0) * ifty + qGreen(y1) * fty) >> Coord::fraction_shift,
(qBlue(y0) * ifty + qBlue(y1) * fty) >> Coord::fraction_shift);
}
// Interpolate only x
else {
int tidx = v.parts.hi*tex->w + u.parts.hi;
QRgb t = tex->data[tidx];
QRgb tnx = tex->data[tidx + 1];
Coord::value_type ftx = u.parts.lo;
Coord::value_type iftx = Coord::fraction_max - ftx;
c = qRgb((qRed(t) * iftx + qRed(tnx) * ftx) >> Coord::fraction_shift,
(qGreen(t) * iftx + qGreen(tnx) * ftx) >> Coord::fraction_shift,
(qBlue(t) * iftx + qBlue(tnx) * ftx) >> Coord::fraction_shift);
}
}
else {
// Interpolate only y
if ( itny < tex->h ) {
int tidx = v.parts.hi*tex->w + u.parts.hi;
QRgb t = tex->data[tidx];
QRgb tny = tex->data[tidx + tex->w];
Coord::value_type fty = v.parts.lo;
Coord::value_type ifty = Coord::fraction_max - fty;
c = qRgb((qRed(t) * ifty + qRed(tny) * fty) >> Coord::fraction_shift,
(qGreen(t) * ifty + qGreen(tny) * fty) >> Coord::fraction_shift,
(qBlue(t) * ifty + qBlue(tny) * fty) >> Coord::fraction_shift);
}
else
// Do not interpolate at all
c = tex->data[v.parts.hi*tex->w +u.parts.hi];
}
}
inline void getTexel(QRgb &c, const QRgb *data, int w, int, Coord u, Coord v) {
c = data[v.parts.hi*w + u.parts.hi];
}
inline void getTexelBilinear(QRgb &c, const QRgb *data, int w, int h, Coord u, Coord v) {
Coord::part_type itnx = u.parts.hi + 1;
Coord::part_type itny = v.parts.hi + 1;
if ( (int)itnx < w ) {
if ( (int)itny < h ) {
int tidx = v.parts.hi*w + u.parts.hi;
QRgb t = data[tidx];
QRgb tnx = data[tidx + 1];
QRgb tny = data[tidx + w];
QRgb tnxy = data[tidx + w + 1];
Coord::value_type ftx = u.parts.lo;
Coord::value_type fty = v.parts.lo;
Coord::value_type iftx = Coord::fraction_max - ftx;
Coord::value_type ifty = Coord::fraction_max - fty;
QRgb y0 = qRgba((qRed(t) * iftx + qRed(tnx) * ftx) >> Coord::fraction_shift,
(qGreen(t) * iftx + qGreen(tnx) * ftx) >> Coord::fraction_shift,
(qBlue(t) * iftx + qBlue(tnx) * ftx) >> Coord::fraction_shift,
(qAlpha(t) * iftx + qAlpha(tnx) * ftx) >> Coord::fraction_shift);
QRgb y1 = qRgba((qRed(tny) * iftx + qRed(tnxy) * ftx) >> Coord::fraction_shift,
(qGreen(tny) * iftx + qGreen(tnxy) * ftx) >> Coord::fraction_shift,
(qBlue(tny) * iftx + qBlue(tnxy) * ftx) >> Coord::fraction_shift,
(qAlpha(tny) * iftx + qAlpha(tnxy) * ftx) >> Coord::fraction_shift);
c = qRgba((qRed(y0) * ifty + qRed(y1) * fty) >> Coord::fraction_shift,
(qGreen(y0) * ifty + qGreen(y1) * fty) >> Coord::fraction_shift,
(qBlue(y0) * ifty + qBlue(y1) * fty) >> Coord::fraction_shift,
(qAlpha(y0) * ifty + qAlpha(y1) * fty) >> Coord::fraction_shift);
}
// Interpolate only x
else {
int tidx = v.parts.hi*w + u.parts.hi;
QRgb t = data[tidx];
QRgb tnx = data[tidx + 1];
Coord::value_type ftx = u.parts.lo;
Coord::value_type iftx = Coord::fraction_max - ftx;
c = qRgba((qRed(t) * iftx + qRed(tnx) * ftx) >> Coord::fraction_shift,
(qGreen(t) * iftx + qGreen(tnx) * ftx) >> Coord::fraction_shift,
(qBlue(t) * iftx + qBlue(tnx) * ftx) >> Coord::fraction_shift,
(qAlpha(t) * iftx + qAlpha(tnx) * ftx) >> Coord::fraction_shift);
}
}
else {
// Interpolate only y
if ( (int)itny < h ) {
int tidx = v.parts.hi*w + u.parts.hi;
QRgb t = data[tidx];
QRgb tny = data[tidx + w];
Coord::value_type fty = v.parts.lo;
Coord::value_type ifty = Coord::fraction_max - fty;
c = qRgba((qRed(t) * ifty + qRed(tny) * fty) >> Coord::fraction_shift,
(qGreen(t) * ifty + qGreen(tny) * fty) >> Coord::fraction_shift,
(qBlue(t) * ifty + qBlue(tny) * fty) >> Coord::fraction_shift,
(qAlpha(t) * ifty + qAlpha(tny) * fty) >> Coord::fraction_shift);
}
else
// Do not interpolate at all
c = data[v.parts.hi*w + u.parts.hi];
}
}
}
}
}