summaryrefslogtreecommitdiff
path: root/include/llmr/geometry/geometry.hpp
blob: 2f321934a7d30a4db40d7c8d03313592df3016f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#ifndef LLMR_GEOMETRY_GEOMETRY
#define LLMR_GEOMETRY_GEOMETRY

#include <llmr/util/pbf.hpp>
#include <llmr/util/noncopyable.hpp>

#include <cstdlib>

namespace llmr {

class Geometry : private util::noncopyable {

public:
    inline explicit Geometry(pbf& data);
  
    enum command : uint8_t {
        end = 0,
        move_to = 1,
        line_to = 2,
        close = 7
    };

    inline command next(int32_t &rx, int32_t &ry);

private:
    pbf& data;
    uint8_t cmd;
    uint32_t length;
    int32_t x, y;
    int32_t ox, oy;
};

Geometry::Geometry(pbf& data)
    : data(data),
      cmd(1),
      length(0),
      x(0), y(0),
      ox(0), oy(0) {}

Geometry::command Geometry::next(int32_t &rx, int32_t &ry) {
    if (data.data < data.end) {
        if (length == 0) {
            uint32_t cmd_length = static_cast<uint32_t>(data.varint());
            cmd = cmd_length & 0x7;
            length = cmd_length >> 3;
        }

        --length;

        if (cmd == move_to || cmd == line_to) {
            rx = (x += data.svarint());
            ry = (y += data.svarint());

            if (cmd == move_to) {
                ox = x;
                oy = y;
                return move_to;
            } else {
                return line_to;
            }
        } else if (cmd == close) {
            rx = ox;
            ry = oy;
            return close;
        } else {
            fprintf(stderr, "unknown command: %d\n", cmd);
            // TODO: gracefully handle geometry parse failures
            return end;
        }
    } else {
        return end;
    }
}

}

#endif