在地图上添加POI

使用Tangram的Marker, 可以在地图上做各种标记, 效果图:

Tangram是通过Marker在地图上添加标记的,Marker分Point, Polyline和Polygon三种, 分别对应点、线、面三种几何体。

Tangram使用统一的Marker接口来管理Marker:

namespace Tangram {
class Map {

public:
    // Add a marker object to the map and return an ID for it; an ID of 0 indicates an invalid marker;
    // the marker will not be drawn until both styling and geometry are set using the functions below.
    MarkerID markerAdd();

    // Remove a marker object from the map; returns true if the marker ID was found and successfully
    // removed, otherwise returns false.
    bool markerRemove(MarkerID _marker);

    // Set the styling for a marker object; _styling is a string of YAML that specifies a 'draw rule'
    // according to the scene file syntax; returns true if the marker ID was found and successfully
    // updated, otherwise returns false.
    bool markerSetStyling(MarkerID _marker, const char* _styling);

    // Set a bitmap to use as the image for a point marker; _data is a buffer of RGBA pixel data with
    // length of _width * _height; pixels are in row-major order beginning from the bottom-left of the
    // image; returns true if the marker ID was found and successfully updated, otherwise returns false.
    bool markerSetBitmap(MarkerID _marker, int _width, int _height, const unsigned int* _data);

    // Set the geometry of a marker to a point at the given coordinates; markers can have their
    // geometry set multiple times with possibly different geometry types; returns true if the
    // marker ID was found and successfully updated, otherwise returns false.
    bool markerSetPoint(MarkerID _marker, LngLat _lngLat);

    // Set the geometry of a marker to a point at the given coordinates; if the marker was previously
    // set to a point, this eases the position over the given duration in seconds with the given EaseType;
    // returns true if the marker ID was found and successfully updated, otherwise returns false.
    bool markerSetPointEased(MarkerID _marker, LngLat _lngLat, float _duration, EaseType _ease);

    // Set the geometry of a marker to a polyline along the given coordinates; _coordinates is a
    // pointer to a sequence of _count LngLats; markers can have their geometry set multiple times
    // with possibly different geometry types; returns true if the marker ID was found and
    // successfully updated, otherwise returns false.
    bool markerSetPolyline(MarkerID _marker, LngLat* _coordinates, int _count);

    // Set the geometry of a marker to a polygon with the given coordinates; _counts is a pointer
    // to a sequence of _rings integers and _coordinates is a pointer to a sequence of LngLats with
    // a total length equal to the sum of _counts; for each integer n in _counts, a polygon is created
    // by taking the next n LngLats from _coordinates, with winding order and internal polygons
    // behaving according to the GeoJSON specification; markers can have their geometry set multiple
    // times with possibly different geometry types; returns true if the marker ID was found and
    // successfully updated, otherwise returns false.
    bool markerSetPolygon(MarkerID _marker, LngLat* _coordinates, int* _counts, int _rings);

    // Set the visibility of a marker object; returns true if the marker ID was found and successfully
    // updated, otherwise returns false.
    bool markerSetVisible(MarkerID _marker, bool _visible);

    // Set the ordering of point marker object relative to other markers; higher values are drawn 'above';
    // returns true if the marker ID was found and successfully updated, otherwise returns false.
    bool markerSetDrawOrder(MarkerID _marker, int _drawOrder);

    // Remove all marker objects from the map; Any marker IDs previously returned from 'markerAdd'
    // are invalidated after this.
    void markerRemoveAll();
};
}

我觉得使用统一的接口来处理Marker在易用性有些欠缺, 因此决定使用单独的class来处理: Marker, Polyline, Polygon.

Tangram使用各种style来处理Marker的显示效果, 可能是对Tangram的实现还没有了解清楚, 暂时没有发现直接给一个Marker加上label的方法, 只好采用了一个hack的方法: 同时生成两个Tangram::Marker, 一个用来显示icon, 另一个用来显示label。

头文件:

class MarkerImpl: public Marker
{
public:
    MarkerImpl(Tangram::Map* map);
    ~MarkerImpl();

    // Mark interface
private:
    virtual void setImage(const std::string &iconURI) override;
    virtual void setTitle(const std::string &title) override;

private:
    Tangram::Map*       m_map;
    Tangram::MarkerID   m_iconID;   //use this marker to show icon
    Tangram::MarkerID   m_labelID;  //use this marker to show label

};

实现

void MarkerImpl::setImage(const std::string &iconURI)
{
    QImage img(QString(iconURI.c_str()));

    int width = img.width();
    int height = img.height();
    auto argb = new unsigned int [width * height];
    for(int h=height-1; h>-1; --h){
        for(int w=0; w<width; ++w){
            int pix = img.pixelColor(w, h).rgba();
            int pb = (pix >> 16) & 0xff;
            int pr = (pix << 16) & 0x00ff0000;
            int pix1 = (pix & 0xff00ff00) | pr | pb;
            argb[w + h*width] = pix1;
        }
    }

    m_map->markerSetBitmap(m_iconID, width, height, argb);

    const char* MARKER_ICON_STYLE = "{ style: 'points', color: 'white', size: [%1px, %1px], order: 100, collide: false }";
    QString iconStyle = QString(MARKER_ICON_STYLE).arg(width).arg(height);
    m_map->markerSetStyling(m_iconID, iconStyle.toStdString().c_str());

    delete[] argb;
}

void MarkerImpl::setTitle(const std::string &title)
{
    const char* MARKER_TEXT_STYLE = "{ style: 'text', text_source: 'function(){ return \"%1\"}', offset: [0px, 24px], text_wrap: false}";
    QString labelStyle = QString(MARKER_TEXT_STYLE).arg(title.c_str());
    m_map->markerSetStyling(m_labelID, labelStyle.toStdString().c_str());
}

 

Tangram的核心特性是可配置性, 通过一个YAML scene文件, 定义不同的style, 可以配置几乎所有的显示效果。 这是一个很大的话题, 以后单独分析

 

posted on 2016-12-06 22:41  btian  阅读(791)  评论(0编辑  收藏  举报

导航