aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/Intersection/Intersections.h
blob: fc4c26c6e7b7dca9aef5a7a88dcb094a0760adba (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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#ifndef Intersections_DEFINE
#define Intersections_DEFINE

class Intersections {
public:
    Intersections()
        : fFlip(0)
#if SK_DEBUG
        , fDepth(0)
#endif
        , fSwap(0)
    {
#if SK_DEBUG
        bzero(fPt, sizeof(fPt));
        bzero(fT, sizeof(fT));
        bzero(fIsCoincident, sizeof(fIsCoincident));
#endif
        reset();
    }

    int coincidentUsed() const {
        if (!fIsCoincident[0]) {
            SkASSERT(!fIsCoincident[0]);
            return 0;
        }
        int count = 0;
        SkDEBUGCODE(int count2 = 0;)
        for (int index = 0; index < fUsed; ++index) {
            if (fIsCoincident[0] & (1 << index)) {
                ++count;
            }
    #if SK_DEBUG
            if (fIsCoincident[1] & (1 << index)) {
                ++count2;
            }
    #endif
        }
        SkASSERT(count == count2);
        return count;
    }

    void offset(int base, double start, double end) {
        for (int index = base; index < fUsed; ++index) {
            double val = fT[fSwap][index];
            val *= end - start;
            val += start;
            fT[fSwap][index] = val;
        }
    }

    // FIXME : does not respect swap
    int insert(double one, double two, const _Point& pt);

    // start if index == 0 : end if index == 1
    void insertCoincident(double one, double two, const _Point& pt) {
        int index = insertSwap(one, two, pt);
        int bit = 1 << index;
        fIsCoincident[0] |= bit;
        fIsCoincident[1] |= bit;
    }

    void insertCoincidentPair(double s1, double e1, double s2, double e2,
            const _Point& startPt, const _Point& endPt);

    int insertSwap(double one, double two, const _Point& pt) {
        if (fSwap) {
            return insert(two, one, pt);
        } else {
            return insert(one, two, pt);
        }
    }

    bool intersected() const {
        return fUsed > 0;
    }

    void removeOne(int index);

    // leaves flip, swap alone
    void reset() {
        fUsed = 0;
        fUnsortable = false;
    }

    void swap() {
        fSwap ^= true;
    }

    void swapPts() {
        int index;
        for (index = 0; index < fUsed; ++index) {
            SkTSwap(fT[0][index], fT[1][index]);
        }
    }

    bool swapped() const {
        return fSwap;
    }

    bool unsortable() const {
        return fUnsortable;
    }

    int used() const {
        return fUsed;
    }

    void downDepth() {
        SkASSERT(--fDepth >= 0);
    }

    void upDepth() {
        SkASSERT(++fDepth < 16);
    }

#if SK_DEBUG
    int depth() const {
        return fDepth;
    }
#endif

    _Point fPt[9];
    double fT[2][9];
    unsigned short fIsCoincident[2]; // bit arrays, one bit set for each coincident T
    unsigned char fUsed;
    bool fFlip;
    bool fUnsortable;
#if SK_DEBUG
    int fDepth;
#endif
protected:
    // used by addCoincident to remove ordinary intersections in range
    void remove(double one, double two, const _Point& startPt, const _Point& endPt);
private:
    bool fSwap;
};

#endif