aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/Intersection/Intersections.h
blob: aed47bd61bd10e87faf37599b7c61385fb1729ab (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
/*
 * 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)
        , fSwap(0)
#if SK_DEBUG
        , fDepth(0)
#endif
    {
        // OPTIMIZE: don't need to be initialized in release
        bzero(fT, sizeof(fT));
        bzero(fCoincidentT, sizeof(fCoincidentT));
        reset();
    }

    void add(double one, double two) {
        for (int index = 0; index < fUsed; ++index) {
            if (approximately_equal(fT[fSwap][index], one)
                    && approximately_equal(fT[fSwap ^ 1][index], two)) {
                return;
            }
        }
        SkASSERT(fUsed < 9);
        fT[fSwap][fUsed] = one;
        fT[fSwap ^ 1][fUsed] = two;
        ++fUsed;
    }

    // start if index == 0 : end if index == 1
    void addCoincident(double one, double two) {
        for (int index = 0; index < fCoincidentUsed; ++index) {
            if (approximately_equal(fCoincidentT[fSwap][index], one)
                    && approximately_equal(fCoincidentT[fSwap ^ 1][index], two)) {
                return;
            }
        }
        SkASSERT(fCoincidentUsed < 9);
        fCoincidentT[fSwap][fCoincidentUsed] = one;
        fCoincidentT[fSwap ^ 1][fCoincidentUsed] = two;
        ++fCoincidentUsed;
    }

    void addCoincident(double s1, double e1, double s2, double e2);

    // FIXME: this is necessary because curve/curve intersections are noisy
    // remove once curve/curve intersections are improved
    void cleanUp();

    int coincidentUsed() const {
        return fCoincidentUsed;
    }

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

    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;
        }
    }

    void insert(double one, double two);
    void insertOne(double t, int side);

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

    bool insertBalanced() const {
        return fUsed == fUsed2;
    }

    // leaves flip, swap alone
    void reset() {
        fUsed = fUsed2 = fCoincidentUsed = 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);
    }

    double fT[2][9];
    double fCoincidentT[2][9];
    int fUsed;
    int fUsed2;
    int fCoincidentUsed;
    bool fFlip;
    bool fUnsortable;
#if SK_DEBUG
    int fDepth;
#endif
private:
    int fSwap;
};

#endif